clearlight
clearlight

Reputation: 12625

What (else) do I need to do to open my iOS app by tapping attachment?

For my iOS 16.x app, I define a custom UTI following in my Info.plist.

It isn't performing as expected. For example, I tap file links or attachments that have the new extension, but I am simply shown a view of the (simple JSON) contents.

Strangely, when I drag a file that has that .custom extension as an attachment into a Messages thread on the Mac, it recognizes it as a type of App Name Document (the Mac seems to properly associate it with my iOS app that I'm building in Xcode on that Mac and running on a real iPhone).

But no matter where I click or tap and hold, in Files app, in Messages, in E-Mail, on http://iCloud.com browsing iCloud drive, it doesn't show me an option to open my app it just displays the contents (simple JSON).

I've implemented the open url delegate method in AppDelegate.swift and the corresponding one in SceneDelegate.swift.

    <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeIdentifier</key>
            <string>llc.company.App-Name-document</string>
            <key>UTTypeConformsTo</key>
            <array>
                <string>public.json</string>
            </array>
            <key>UTTypeDescription</key>
            <string>App Name Document</string>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                <array>
                    <string>custom</string>
                </array>
            </dict>
        </dict>
    </array>
    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>App Name Document</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>llc.company.App-Name-document</string>
            </array>
            <key>LSHandlerRank</key>
            <string>Owner</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
        </dict>
    </array>

Upvotes: 0

Views: 379

Answers (1)

clearlight
clearlight

Reputation: 12625

GOT IT WORKING... But it is finicky and insufficiently documented, IMO.

It took a lot of experimentation to figure out.


First, as to dialog in comments above with @HangerRash: Though you *can* use a generic UTI like `public.data`, it won't know how to display the data (because public.data merely indicates it's a generic bytestream). Thus, it won't open the file up in viewer, which where Messages and the Files app on the iOS device reveal share menu [↑] icon, which lets you share the attachment with your app.

By inheriting from the base UTI with "public.json" in my case it works. I'm sure any UTI that it figure out how to show the user the content of the attachment will work (at least in Messages and Files app), whereas the Mail app is a little more forgiving and will let you share a public.data attachment.

As of iOS 16 and whichever version introduced SceneDelegate (I think iOS 13+), it sends the URL of the attachment to the app via SceneDelegate:

 func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)

In an answer to another question (which I've yet to verify as I need to implement more code before I can test it), it was mentioned that if the app isn't already running when the attachment is shared, this delegate method will be called instead, wherein the attachment URL will be passed via options argument:

 func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)

Finally I can confirm that (A) CFBundleTypeRole (e.g. Editor/Viewer) wasn't necessary in my case.

Upvotes: 0

Related Questions