Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

App Icon Generator is no longer needed with Xcode 14

How do you stay current as a Swift developer?

Let me do the hard work and join 19,138 developers that stay up to date using my weekly newsletter:

An App Icon Generator generates all required app icon sizes based on a single-size icon input file. Creating and dragging all those app icons into Xcode is often tiresome since we’ve all asked ourselves: “Why can’t Xcode just generate the sizes for us based on a single file?”

Well, there’s good news! During WWDC 2022, Apple announced support for single-size app icons, allowing you to only drag in a single app icon image into your asset catalog. I was curious to see how this works and how it would affect app sizes, so I decided to dive in.

Configuring a single app icon for all sizes

You can configure your Assets catalog in Xcode to use a single size for all app icons from within the Attributes Inspector panel:

Select single size from within the Attributes Inspector to no longer depend on App Icon Generators.
Select single size from within the Attributes Inspector to no longer depend on App Icon Generators.

The overview for your app icon will change into a single 1024×1024 app icon:

Using a single-size 1024x1024 app icon for all individual sizes.
Using a single 1024×1024 app icon for all individual sizes.

Your project will now automatically use this single 1024×1024 app icon to resize individual icons to their target size.

Can I override individual app icon sizes?

There’s no option to override individual app icon sizes while falling back on the single app icon for other sizes. In other words, if you want to configure specific app icons for certain sizes, you’ll have to provide an app icon for all individual sizes. An App Icon generator might still be helpful for these cases.

Which platforms support single app icon sizes?

iOS, iPadOS, and watchOS are supported. You could argue extensions like App Clips are supported since they reuse the App Icon of your main project. You still need to define all sizes individually for macOS.

How does a single app icon affect my app’s total size?

When Apple announced the single-size app icon feature, I was immediately interested in investigating the effect on app size. It’s already great to step away from app icon generators, but it’s even better when you realize you’ll get an easy way to reduce your app’s total size. App size is critical when maintaining app clips with a limited 10MB size.

I decided to dive in and investigate archives for single-size app icons compared to individual size configured app icons. I exported the archives for development with app thinning enabled for an iPhone 13 Pro:

Exporting an archive with App Thinning enabled to evaluate the app size.
Exporting an archive with App Thinning enabled to allow evaluating the app size.

App Thinning makes sure only to include assets required for the active device. In this case, the outcome will only have the necessary assets for an iPhone 13 Pro.

You’ll receive an App Thinning Size Report.txt as a result, including details about the exported .ipa (iOS App Store Package) file.

First up is the thinning size report for the archive with individual app icon sizes:

App + On Demand Resources size: 5,6 MB compressed, 17,7 MB uncompressed
App size: 5,6 MB compressed, 17,7 MB uncompressed
On Demand Resources size: Zero KB compressed, Zero KB uncompressed

The single-size icon archive resulted in the following output:

App + On Demand Resources size: 5,4 MB compressed, 17,5 MB uncompressed
App size: 5,4 MB compressed, 17,5 MB uncompressed
On Demand Resources size: Zero KB compressed, Zero KB uncompressed

In the case of my Stock Analyzer app, I reduced the size by 0.2 MB. However, my icon files are relatively small in size, so the difference might be higher when you’re using more detailed app icons. The size of all icons minus the 1024×1024 aligned with the 0.2 MB size.

Diving into the bundled assets

I wasn’t delighted with the underlying details, so I decided to take it one step further. I changed the file extension of the .ipa to .zip, allowing me to extract the inner contents:

The resulting .app file after extracting  single-size defined .ipa file.
The resulting .app file after extracting the .ipa file.

The output will contain a Payload folder with an .app file inside. Right-click the .app file and tap Show Package Contents will show you the insides of your app:

The inner contents of an .app file.
The inner contents of a .app file.

Checking out the contents of your .app file regularly is a good practice as you’ll get insights into bundled contents. For example, during this process, I realized I’m bundling my README.md while it’s not even used in the app. In other words, it’s a waste of size, affecting my outcome app size!

Interesting enough, you’ll notice the size of the Assets.car being larger for the single-size .app file. In my case, the size was 228KB vs. 55KB for the individual sizes app, which is most likely due to having to bundle the 1024×1024 file for single-size icons. Though, remember the outcome of the App Thinning report, which is leading in terms of the output app size.

Analyzing the Assets.car file

I finalized my research by analyzing the Assets.car file using xcrun --sdk iphoneos assetutil --info <path to Assets.car>.

The output for the app with individual app icons looked as follows:

[
  {
    "Appearances" : {
      "UIAppearanceAny" : 0
    },
    "AssetStorageVersion" : "Xcode 14.0 (14A5228q) via AssetCatalogSimulatorAgent",
    "Authoring Tool" : "@(#)PROGRAM:CoreThemeDefinition  PROJECT:CoreThemeDefinition-545\n",
    "CoreUIVersion" : 784,
    "DumpToolVersion" : 784,
    "Key Format" : [
      "kCRThemeScaleName",
      "kCRThemeIdiomName",
      "kCRThemeSubtypeName",
      "kCRThemeDimension2Name",
      "kCRThemeDimension1Name",
      "kCRThemeIdentifierName",
      "kCRThemeElementName",
      "kCRThemePartName"
    ],
    "MainVersion" : "@(#)PROGRAM:CoreUI  PROJECT:CoreUI-784\n",
    "Platform" : "ios",
    "PlatformVersion" : "15.0",
    "SchemaVersion" : 2,
    "StorageVersion" : 17,
    "ThinningParameters" : "carutil 784.000000, thinned <mode app> <idiom 1> <subtype 2340> <subtypefallback *> <scale 3> <gamut 1> <graphics 8> <graphicsfallback *> <memory 3> <deployment- 7> <hostedIdioms (4)> <removed 22>",
    "Timestamp" : 1654588514
  },
  {
    "AssetType" : "Color",
    "Color components" : [
      0.012000000104308128,
      0.55299997329711914,
      0.93699997663497925,
      1
    ],
    "Colorspace" : "srgb",
    "Idiom" : "universal",
    "Name" : "AccentColor",
    "NameIdentifier" : 20419,
    "Scale" : 1
  },
  {
    "AssetType" : "Icon Image",
    "BitsPerComponent" : 8,
    "ColorModel" : "RGB",
    "Colorspace" : "srgb",
    "Compression" : "lzfse",
    "Encoding" : "ARGB",
    "Icon Index" : 0,
    "Idiom" : "phone",
    "Name" : "AppIcon",
    "NameIdentifier" : 6849,
    "Opaque" : true,
    "PixelHeight" : 60,
    "PixelWidth" : 60,
    "RenditionName" : "[email protected]",
    "Scale" : 3,
    "SHA1Digest" : "1BA15ECB895C6DB3D9C3F2A5EC8879FAE3398B9FAB5603749AE59EA59C574837",
    "SizeOnDisk" : 338
  },
  {
    "AssetType" : "Icon Image",
    "BitsPerComponent" : 8,
    "ColorModel" : "RGB",
    "Colorspace" : "srgb",
    "Compression" : "lzfse",
    "Encoding" : "ARGB",
    "Icon Index" : 1,
    "Idiom" : "phone",
    "Name" : "AppIcon",
    "NameIdentifier" : 6849,
    "Opaque" : true,
    "PixelHeight" : 87,
    "PixelWidth" : 87,
    "RenditionName" : "[email protected]",
    "Scale" : 3,
    "SHA1Digest" : "421599995A0F9C9F0E404822A6EC8C6988674D85C63AA69D9F6937896ED7E28B",
    "SizeOnDisk" : 334
  },
  {
    "AssetType" : "Icon Image",
    "BitsPerComponent" : 8,
    "ColorModel" : "RGB",
    "Colorspace" : "srgb",
    "Compression" : "lzfse",
    "Encoding" : "ARGB",
    "Icon Index" : 2,
    "Idiom" : "phone",
    "Name" : "AppIcon",
    "NameIdentifier" : 6849,
    "Opaque" : true,
    "PixelHeight" : 120,
    "PixelWidth" : 120,
    "RenditionName" : "[email protected]",
    "Scale" : 3,
    "SHA1Digest" : "E8BB38F5724830625968B6174A6B74927F006BE288E8067896AD1BD9F764875F",
    "SizeOnDisk" : 334
  },
  {
    "AssetType" : "Icon Image",
    "BitsPerComponent" : 8,
    "ColorModel" : "RGB",
    "Colorspace" : "srgb",
    "Compression" : "lzfse",
    "Encoding" : "ARGB",
    "Icon Index" : 3,
    "Idiom" : "phone",
    "Name" : "AppIcon",
    "NameIdentifier" : 6849,
    "Opaque" : true,
    "PixelHeight" : 180,
    "PixelWidth" : 180,
    "RenditionName" : "[email protected]",
    "Scale" : 3,
    "SHA1Digest" : "5329D24575A671A5AA17AC4F9D49BBA652E0581744A857646106B4AF82A3C5E8",
    "SizeOnDisk" : 334
  },
  {
    "AssetType" : "MultiSized Image",
    "Idiom" : "phone",
    "Name" : "AppIcon",
    "NameIdentifier" : 6849,
    "Scale" : 1,
    "Sizes" : [
      "20x20 index:0 idiom:phone",
      "29x29 index:1 idiom:phone",
      "40x40 index:2 idiom:phone",
      "60x60 index:3 idiom:phone"
    ]
  },
  {
    "AssetType" : "PackedImage",
    "BitsPerComponent" : 8,
    "ColorModel" : "RGB",
    "Colorspace" : "srgb",
    "Compression" : "lzfse",
    "Encoding" : "ARGB",
    "Idiom" : "phone",
    "Name" : "ZZZZPackedAsset-3.1.0-gamut0",
    "Opaque" : true,
    "PixelHeight" : 272,
    "PixelWidth" : 306,
    "RenditionName" : "ZZZZPackedAsset-3.1.0-gamut0",
    "Scale" : 3,
    "SHA1Digest" : "2CEA5E74A6195E748C7F8BD757F8DD94DFFBBC7CFDCC39D62C5EE0ABC4B25BBC",
    "SizeOnDisk" : 31082
  },
  {
    "AssetType" : "PackedImage",
    "BitsPerComponent" : 8,
    "ColorModel" : "RGB",
    "Colorspace" : "srgb",
    "Compression" : "lzfse",
    "Dimension1" : 1,
    "Encoding" : "ARGB",
    "Idiom" : "phone",
    "Name" : "ZZZZPackedAsset-3.1.0-gamut0",
    "Opaque" : true,
    "PixelHeight" : 64,
    "PixelWidth" : 64,
    "RenditionName" : "ZZZZPackedAsset-3.1.0-gamut0",
    "Scale" : 3,
    "SHA1Digest" : "CE92DA607E9E5291405ED8195C283872355E55DBA844B5E14AD0107D6AAFE4D2",
    "SizeOnDisk" : 4008
  }
]

While the one with a single-size defined app icon looks as follows:

[
  {
    "Appearances" : {
      "UIAppearanceAny" : 0
    },
    "AssetStorageVersion" : "Xcode 14.0 (14A5228q) via AssetCatalogSimulatorAgent",
    "Authoring Tool" : "@(#)PROGRAM:CoreThemeDefinition  PROJECT:CoreThemeDefinition-545\n",
    "CoreUIVersion" : 784,
    "DumpToolVersion" : 784,
    "Key Format" : [
      "kCRThemeScaleName",
      "kCRThemeIdiomName",
      "kCRThemeSubtypeName",
      "kCRThemeDimension2Name",
      "kCRThemeDimension1Name",
      "kCRThemeIdentifierName",
      "kCRThemeElementName",
      "kCRThemePartName"
    ],
    "MainVersion" : "@(#)PROGRAM:CoreUI  PROJECT:CoreUI-784\n",
    "Platform" : "ios",
    "PlatformVersion" : "15.0",
    "SchemaVersion" : 2,
    "StorageVersion" : 17,
    "ThinningParameters" : "carutil 784.000000, thinned <mode app> <idiom 1> <subtype 2340> <subtypefallback *> <scale 3> <gamut 1> <graphics 8> <graphicsfallback *> <memory 3> <deployment- 7> <hostedIdioms (4)> <removed 23>",
    "Timestamp" : 1654588790
  },
  {
    "AssetType" : "Color",
    "Color components" : [
      0.012000000104308128,
      0.55299997329711914,
      0.93699997663497925,
      1
    ],
    "Colorspace" : "srgb",
    "Idiom" : "universal",
    "Name" : "AccentColor",
    "NameIdentifier" : 20419,
    "Scale" : 1
  },
  {
    "AssetType" : "Icon Image",
    "BitsPerComponent" : 8,
    "ColorModel" : "RGB",
    "Colorspace" : "srgb",
    "Compression" : "lzfse",
    "Encoding" : "ARGB",
    "Icon Index" : 7,
    "Idiom" : "phone",
    "Name" : "AppIcon",
    "NameIdentifier" : 6849,
    "Opaque" : true,
    "PixelHeight" : 1024,
    "PixelWidth" : 1024,
    "RenditionName" : "Icon.png",
    "Scale" : 1,
    "SHA1Digest" : "1ECBD8487D88A01208D239EC7B5936173A38ABBEFF091D0064DFA9D3F1FD6401",
    "SizeOnDisk" : 209897
  },
  {
    "AssetType" : "MultiSized Image",
    "Idiom" : "phone",
    "Name" : "AppIcon",
    "NameIdentifier" : 6849,
    "Scale" : 1,
    "Sizes" : [
      "1024x1024 index:7 idiom:phone"
    ]
  }
]

The above output might look obvious since we only included a single app icon in the assets catalog. Still, I would not have been surprised if Xcode generated the individual app icons during archiving. While I haven’t found evidence of how it exactly works, it looks like individual icons resize to their target sizes at the moment of use.

Conclusion

App Icon Generators are no longer needed if you’re using the new single-size app icons in Xcode 14. You can still define individual app icons, but it does require you to define all individual sizes. The chances are high that your app size will reduce after configuring a single app icon only since the OS can reuse the single app icon file for all target sizes.

If you like to improve your Xcode knowledge, even more, check out the Xcode category page. Feel free to contact me or tweet me on Twitter if you have any additional tips or feedback.

Thanks!

 
Antoine van der Lee

Written by

Antoine van der Lee

iOS Developer since 2010, former Staff iOS Engineer at WeTransfer and currently full-time Indie Developer & Founder at SwiftLee. Writing a new blog post every week related to Swift, iOS and Xcode. Regular speaker and workshop host.

Are you ready to

Turn your side projects into independence?

Learn my proven steps to transform your passion into profit.