How can I create an image to be shown for a custom exported document type for an iOS App?

41 Views Asked by At

I'm exporting a custom document type in my app by adding UTExportTypeDeclarations and CFBundleDocumentTypes to info.plist.

How can I get an custom image associated with my exported document type?

When I export a document type that's based on a public.text conformant UTI (UTTypeConformsTo key), I always get a generic text document icon in messages document attachments of my custom file type, no matter what I do.

I've tried the techniques I've seen on Stack Overflow and on the Internet, that entail setting CFBundleTypeIconFiles subkey of CFBundlesDocumentTypes (in info.plist) with values being an array of file name strings in the key's dictionary, and I've tried the alternative name of the key, CFBundleTypeIconFile (which apparently is the macOS app variant of the key).

I've tried tried making the string values of CFBundleTypeIconFiles array be simple names of image files in the resources bundle, and, alternatively, I've tried making the string array values the names of images in the Asset catalog, but neither have worked for my case.

Nor is it clear to me exactly which size images I should include in that list of icon references, since screen resolutions and icon requirements have changed over the years.

Worse, when I do specify CFBundleTypeIconFiles key, apparently some state gets badly messed up and the AppIcon will never be used as the default for any UTI type (as it is for custom exported types defined with some public.data conforming UTI base type).

In fact, when I do try to specify my own images, the only sure way I've seen to recover default behaviors is to completely reset and reinstall iOS on the iPhone! Sometimes but not always logging out of iCloud, and doing a reset all (without removing content) has worked.

Note: I'm doing a Q & A style answer here to save people the confusion and time, since this isn't a well-enough documented area

1

There are 1 best solutions below

0
clearlight On

Apparently as of iOS 16.6, XCode 14.3.1 (in Aug 2023), the relevant document is Apple's 2015 document (originally Mac-only document) on UTI types. And while that is a very old document, it seems to be the latest and the relevant one. It says to use UTTypeIconFile and to set the value to yourfile.icns

The UTTypeIconFile subkey goes under the UTExportedTypeDeclarations (or UTImportedTypeDeclarations depending on what you're doing) in info.plist.

A very easy way to generate the .icns file (which contains the icon at various resolutions), is to take an image such as the AppIcon image, 1024x1024 and drag it into the window of the classic (totally free) macOS App Store app image2icon and have it export it as .icns.

Add the .icns file to your app in XCode, which by default it will get copied into the app's resource bundle when the app launches, which is enough for the system to find and use it.

Then it should show up as the icon when you're exporting custom app extension. I've tested it for public.text and public.json (which is a conformant type of public.text), public.data, and public.content type UTIs.

    <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeConformsTo</key>
            <array>
                <string>public.json</string>
            </array>
            <key>UTTypeIconFile</key>
            <string>AppIconMirror.icns</string>
            <key>UTTypeDescription</key>
            <string>My App Document</string>
            <key>UTTypeIdentifier</key>
            <string>com.mydomain.document</string>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                <array>
                    <string>myext</string>
                </array>
            </dict>
        </dict>
    </array>
    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>My App Document</string>
            <key>LSHandlerRank</key>
            <string>Owner</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>com.mydomain.document</string>
            </array>
        </dict>
    </array>