How to create app icons for macOS 26 and maintain compatibility with older OS's

macOS26 takes care of this automatically. You do not need to make an new specific app icon for macOS26

That’s because your app icon does not follow the Apple required design/size. If it was, it is ‘converted’ correctly without a border.

This is correct in that older icons properly sized will avoid the gray border. Icons designed for Tahoe will still look nicer as they will have proper effects versus Tahoe’s attempt to apply that kind of style to older icons (it seems to detect edges and do some kind of extruding/lighting effect).

Apple’s templates for icons are in the macOS Sequoia section of the Apple Design Resources page.

Apps I released pre-Tahoe that adhere to these designs look fine in Tahoe.

I was poking around developer downloads yesterday and noticed an icon composer app for Tahoe icons. I was curious, but do not know the backwards compatibility nor how to use the generated icons with Xojo.

Icon Composer is for making “layered icons out of Liquid Glass”. It would be appropriate for Tahoe icons but not for making icons for older macOS versions. It has PNG export but this is for making “a flattened version of your icon for marketing and communication needs” not icons for ICNS file (hence it uses lighting effects by default).

[various things about design size / red logo size]

This shouldn’t matter. The icons just have to be made correctly.

It is possible that this stuff requires the app to be built with the macOS 26 SDK. FYI

I didn’t see a difference in behavior when experimenting with this variable.

How To

Make pre-Tahoe icons using Apple’s design resources for Photoshop and Sketch. Export to PNGs. Use these in Xojo or package into your own ICNS file that you copy into the executable with build automation.

Make an icon for Tahoe with Icon Composer. Save it to a “.icon” file. PNG exports are not applicable here. Xojo makes “App.icns” so name it “App.icon”.

Package the App.icon to Assets.car (reference):

actool App.icon \
	--compile . \
	--app-icon App \
	--enable-on-demand-resources NO \
	--development-region en \
	--target-device mac \
	--platform macosx \
	--enable-icon-stack-fallback-generation=disabled \
	--include-all-app-icons \
	--minimum-deployment-target 10.14 \
	--output-partial-info-plist /dev/null

Use build automation to copy the Assets.car file to the Resources folder.

Go to the macOS build settings and add a property list entry for a string with key CFBundleIconName and value of “App”.

This should use the App.icon resource in Assets.car on Tahoe and the App.icns resource on pre-Tahoe. Even without the App.icon/Assets.car icon, your icon should still look fine (no gray border) with only the App.icns file generated by Xojo as long as it adheres to Apple’s design template.

Working example:
Tahoe Icon Example.zip (216.8 KB)

1 Like

Join the Resistance!
Link

10 Likes

Thank you for this. I haven’t yet tested on older systems but this is working. I only found that the actool command could not find the file unless it received the full path to the file. I had changed the Terminal directory to that containing the file, but that wasn’t enough. Didn’t take too long to figure out :slight_smile:

Future Jerry: the legacy icon appears as expected on Sequoia. :slight_smile:

Would you post the actual actool command you used? I did supply the full pathname, and Terminal keeps telling me that “App.icon” isn’t found (or doesn’t exist, I forget which).

actool /Users/jerry/blah/blah/blah/Icons/Tahoe/App.icon
–compile output
–app-icon App
–enable-on-demand-resources NO
–development-region en
–target-device mac
–platform macosx
–enable-icon-stack-fallback-generation=disabled
–include-all-app-icons
–minimum-deployment-target 10.13.6
–output-partial-info-plist /dev/null

I created an ‘output’ directory in my user root, as an argument for –compile. This came from the reference to which Travis linked. I am living on the edge with this particular project, and still supporting High Sierra. Therefore, I modified the minimum target (which may not matter in this case.)

In case none of you noticed… the .icon format that Image Composer outputs is actually a package containing a folder of images and a json file.

2 Likes

Works great, thank you!

It’s quite easy to draw directly to the dock icon which allows to escape the squircle hell. But Xojo apps usually don’t start fast enough so that this looks rather weird. Or I need to experiment some more.

So the secret for compatibility is: Xojo should create an App.icns from provided images and include it, Pre Tahoe OS will use it. Xojo need a way to accept a new App.icon created externally, and Xojo include it into the assets catalog of the app, so Tahoe will use it instead.

1 Like

@Travis_Hicks @Jerry_Fritschle Thank you for your help. It took a bit of effort to follow the steps correctly, but it finally worked. Along the way I found a bug in the macOS 26 Finder where successive builds without any changes would render the icon differently (one time it would have the thick border, the next it would look perfect – in the former case, doing a Get Info in the Finder would update the icon to the correct appearance).

1 Like

I noticed that Finder was better about updating the appearance if the version number was incremented. In trying to figure it out, I ended up with a bunch of copies of the same app with different icon internals but the same version number. I think there’s some caching going on. Changing the version number seemed to force a refresh though.

@Travis_Hicks : how do I use the command? I only get errors “Not enough arguments provided; where is the input document to operate on?”.

See above for the example posted by Jerry Fritschle above. It worked for me when I susbstituted my own file paths for the icon and the folder to receive the output.

@Beatrix_Willius I gave the exact command I used, so I’m not sure why it isn’t working for others. I’m using macOS/Xcode 26, so maybe it works differently in older versions. For the command…

actool App.icon \
	--compile . \
	--app-icon App \
	--enable-on-demand-resources NO \
	--development-region en \
	--target-device mac \
	--platform macosx \
	--enable-icon-stack-fallback-generation=disabled \
	--include-all-app-icons \
	--minimum-deployment-target 10.14 \
	--output-partial-info-plist /dev/null

App.icon is the input. For me it works if my working directory is where the file is, otherwise you’d have to specify a relative or full path. --compile . is to have it write the output to the current working directory. You’d need to change that if you’re providing relative or full paths and want the output to be next to the input.

Here’s the same command without line continuation if that helps:

actool App.icon --compile . --app-icon App --enable-on-demand-resources NO --development-region en --target-device mac --platform macosx --enable-icon-stack-fallback-generation=disabled --include-all-app-icons --minimum-deployment-target 10.14 --output-partial-info-plist /dev/null

Also take a look at the MakeAssetsFromIcon.command shell script I provided in my Tahoe Icon Example above. For me I can just double-click this file and it will open a new Terminal window, switch to the directory the script is in (via line 2 of the shell script), and then perform the command with input and output in the same folder as the script.

Double-clicking the script doesn’t work at all because macOS doesn’t trust anything:

I changed the paths and the result is empty. I’ll try again tomorrow.

The first time I tried to run actool it gave an error saying I needed to run…

xcodebuild -runFirstLaunch

…and agree to various license agreements. After that actool worked fine. Maybe you need to do something like that to get it to work?

Double-clicking the script doesn’t work at all because macOS doesn’t trust anything:

Right, right. You can probably just strip the quarantine flag from the file:

xattr -d com.apple.quarantine <file>

Or remove all extended attributes from the download before unzipping:

xattr -c "Tahoe Icon Example.zip"

Also the file is just a text file, so you can just copy it out to your own shell script. Just make it executable with chmod +x <file>.

What do you do if you already have an Assets.car being generated from an xcassets file? It doesn’t seem possible to add the App.icon file to the xcassets file.

Edit: I added --app-icon ""${PROJECT_PATH}/App.icon"" --output-partial-info-plist /dev/null to my build command, as well as the CFBundleIconName key, but Tahoe is still picking up the older icon. The good news is Tahoe’s ability to adapt my existing app icon is astonishingly good, so I might not care more. I just can’t figure out how to get it to actually work. Only thing I didn’t do was add my App.icon file to my bundle resources, because that seems pointless since I’m baking the icon into the assets file.

1 Like

Isn’t .xcassets just a folder (displayed as a package/bundle/whatever)? Can’t you just add the icon file to the folder before packaging it to Assets.car?

No similar to the icon file, it has a manifest. You’re not meant to just add stuff to it, you’re supposed to edit it with Xcode. Compiling the icon into the asset file doesn’t appear to do anything either, as I don’t see the new icon in the file. So still trying to figure this out.