Setting a custom icon for documents

I'm trying to set custom Icons for my documents created in a Mac Catalyst app. The icon I defined appears on iOS apps fine. But on my mac they all have a generic icon. I have added the CFBundleTypeIcons key to my info.plist and added an .icns file to my app but it changes nothing. What am I not doing here that I should be?

Answered by DTS Engineer in 799767022

To set up an icon for a custom document type, I'd do the following:

  1. Specify the icon file using this Info.plist entry: CFBundleDocumentTypes > CFBundleTypeIconFile:
 <key>CFBundleDocumentTypes</key>
    <array>
           <key>CFBundleTypeIconFile</key>
           <string>Your_Icon_File.icns</string>
           ……
        </dict>
    </array>
  1. If you export the document type, specify the icon file using this Info.plist entry: UTExportedTypeDeclarations > UTTypeIcons > UTTypeIconName:
 <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
           …...
            <key>UTTypeIcons</key>
            <dict>
                <key>UTTypeIconName</key>
                <string>Your_Icon_File_Name</string>
            </dict>
           …...
        </dict>
    </array>
  1. Implement a Thumbnail extension for your app. This provides a thumbnail based on the document content, and works around the corner cases where some system components don't respect the icon specified in the Info.plist. The topic is covered in Providing Thumbnails of Your Custom File Types.

It seems that you have done #1 and #2, and so I'd suggest that you do #3 to see if that works – If it doesn't, which indicates that something in the macCatalyst environment goes wrong, I’d suggest that you file a feedback report (http://developer.apple.com/bug-reporting/) and share your report ID here.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

To set up an icon for a custom document type, I'd do the following:

  1. Specify the icon file using this Info.plist entry: CFBundleDocumentTypes > CFBundleTypeIconFile:
 <key>CFBundleDocumentTypes</key>
    <array>
           <key>CFBundleTypeIconFile</key>
           <string>Your_Icon_File.icns</string>
           ……
        </dict>
    </array>
  1. If you export the document type, specify the icon file using this Info.plist entry: UTExportedTypeDeclarations > UTTypeIcons > UTTypeIconName:
 <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
           …...
            <key>UTTypeIcons</key>
            <dict>
                <key>UTTypeIconName</key>
                <string>Your_Icon_File_Name</string>
            </dict>
           …...
        </dict>
    </array>
  1. Implement a Thumbnail extension for your app. This provides a thumbnail based on the document content, and works around the corner cases where some system components don't respect the icon specified in the Info.plist. The topic is covered in Providing Thumbnails of Your Custom File Types.

It seems that you have done #1 and #2, and so I'd suggest that you do #3 to see if that works – If it doesn't, which indicates that something in the macCatalyst environment goes wrong, I’d suggest that you file a feedback report (http://developer.apple.com/bug-reporting/) and share your report ID here.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Accepted Answer

A few small things to add here from the broader system side:

  1. The Finder can be very “picky” about the exact configuration of icon files, so you need to be sure you’ve included “everything”. In the past I've used very simple icons (typically a solid block of a single color) and then simply filled EVERY possible entry in the icon set. It can be all to easy to think that something is failing when what's actually going on is that the system is choosing to use the ONE icon size you happened to have missed.

  2. The actual icon assignment process is driven by LaunchServices and developer work patterns* can create strange behaviors that wouldn’t happen on any customer install. For example, if you have multiple instances of the same app on your machine, the icon can be missing (or different) because LS has decided that the “other” app copy is one it should consider “authoritative”. More broadly, I’ve seen many cases where the developers app was seeing odd behavior that never happens in real world usage, simply because the system was tracking so many different copies of their app that the development build they were trying to test wasn't want LaunchServices was using for "their app".

  • For example, Xcode is basically uninstalling/reinstalling your app every time it does a full rebuild. That could easily be 10s or 100s of times per day, something none (I hope) of your users would ever do. Similarly, most users don't install apps 5 level into a directory (~/Library/) that isn't even visible in the base install.

For developer's who run into problems with this, what I actually suggest is creating a new/copy project with a different bundle ID than you’re actual app, set up the configuration that should be “right”, copy your new build of that app into /Applications/, then run the app out of that location. Basically, replicate how the system and your users will interact with your app instead of just going through the typical Xcode development flow. Once you've got a configuration that works, you can then merge that configuration back into your main project. That new configuration tends to either immediately work or self correct with more development time or intentional testing (like copying and running out of "/Applications/").

Finally a quick comment on the macCatalyst side of this:

I'm trying to set custom Icons for my documents created in a Mac Catalyst app.

The biggest core difference between iOS and macOS is that macOS's "defintion" of a "valid" app is FAR broader than iOS's. The difference between a AppKit and UIKit apps are FAR smaller than the differences between an XWindows, Java, or Python application (all of which can run on macOS). A big part of why those other runtimes work is because of how issues like icon mapping are handled through plist's not code. However, what can really matter here is this:

...copy your new build of that app into /Applications/, then run the app out of that location

Exactly how LaunchServices registration works isn't something we've ever really documented, however, the best way to guarantee that an app registered properly is to run the app out of "/Applications".

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Setting a custom icon for documents
 
 
Q