0

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>
jnpdx
  • 45,847
  • 6
  • 64
  • 94
clearlight
  • 12,255
  • 11
  • 57
  • 75
  • 1
    With your app installed, try rebooting the iOS device to see if that helps iOS recognize your app as supporting that UTI. – HangarRash Aug 13 '23 at 02:26
  • @HangarRash I edited it to show the initial key line. And no it's all defined at the bottom of the PLIST. I've rebooted the phone several times but after deleting the app and then installed the app fresh on the phone. I'll try rebooting after installing the app. – clearlight Aug 13 '23 at 02:32
  • Why not list your app as supporting json files? Why the custom extension? Are these JSON files of a specific format that your app generates? Do you want other apps to be able to open your app's JSON files or should they only work with your app? – HangarRash Aug 13 '23 at 02:45
  • Now I'm not sure if 'public.json' is really a thing. I don't see it listed in apple supported UTIs. Maybe I should try 'public.text'. Will experiment with that. As far as my custom type... well one advantage is the branding, and app-specific association so if someone gets one of my app-specific configuration files it will be the only candidate for apps to potentially open in the context of that document, which I like a lot https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple_ref/doc/uid/TP40009259 – clearlight Aug 13 '23 at 03:22
  • See the docs for `UTType.json`. `public.json` is correct. – HangarRash Aug 13 '23 at 03:24
  • You could save the JSON string as Data (utf8 encoding) and setup your exported type as `public.data`. Maybe that will cause less confusion than being plain JSON. But of course that only works if you don't want other apps to be able to use your file as regular JSON. – HangarRash Aug 13 '23 at 03:26
  • Thanks. Yes, I've been experimenting with public.data, and the difference is that it makes no assumption about the content when I do that (it won't show me the data in a viewer, like it does with public.json). But in *both* cases I notice Messages (on the Mac) instantly reflects the changes I make to UTTypeDescription key's value, when I build/upload iPhone from XCode, as the description it shows for the attachment. It just doesn't give me the option of opening the app. So I don't think the inherited UTI is the issue and will later weigh which I prefer, public.json, or public.data. – clearlight Aug 13 '23 at 03:50

1 Answers1

0

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.

clearlight
  • 12,255
  • 11
  • 57
  • 75
  • call out to @matt for the cited info. – clearlight Aug 13 '23 at 05:59
  • 1) So now I'm confused what your issue was. Was your issue that your app didn't appear as an option at all until you added the scene delegate method, or was your issue that you could select your app for the file but due to the lack of delegate method, the app didn't actual open the file? All my comments were based on thinking that the issue was that your app didn't appear at all as an option for the file. 2) In the Files app, if a file is public.data or something that can't be previewed, just long press on the file and select Share from the menu. – HangarRash Aug 13 '23 at 06:16
  • @HangarRash, I was mostly testing the preferred use case where people will be sharing the config data through Messages app, and in that case long press was not working for public.data, and I also didn't realize I had to open the app via the share menu, I was expecting something more proactive from the OS to prompt me about the app to open or a confirmation dialog or something. It may be that Files app shows more options for public.data, but I didn't see them and I was trying a lot of different things. May have missed something. – clearlight Aug 13 '23 at 06:28
  • With public.data for a Messages attachment you don't get any option to share unless you're looking at the content of the attachment, apparently. I'd love to be wrong. – clearlight Aug 13 '23 at 06:29
  • But what about my first question? With public.json, did your app appear as on option on the share sheet at all or did adding the scene delegate make it start appearing on the share sheet? – HangarRash Aug 13 '23 at 06:35