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:
The overview for your app icon will change into a single 1024×1024 app icon:
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:
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 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:
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!