File types association with my app

1.1k views Asked by At

My app is capable exporting and importing txt files. CFBundleDocumentTypes and UTExportedTypeDeclarations in my .plist are as follows:

<key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeIconFiles</key>
            <array>
                <string>Icon60@2x</string>
            </array>
            <key>CFBundleTypeName</key>
            <string>CSV</string>
            <key>CFBundleTypeRole</key>
            <string>Default</string>
            <key>LSHandlerRank</key>
            <string>Default</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.text</string>
            </array>
        </dict>
    </array>

<key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeConformsTo</key>
            <array>
                <string>public.text</string>
            </array>
            <key>UTTypeDescription</key>
            <string>CSV</string>
            <key>UTTypeIdentifier</key>
            <string>public.text</string>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                <string>csv</string>
                <key>public.mime-type</key>
                <string>application/myApp</string>
            </dict>
        </dict>
    </array>

Exporting works as expected, no issues. Importing also works well, but only with files which are stored outside of my app iCloud folder, i.e. when I tap a .txt file from mail or generic iCloud folder I can see my app in "Import with ..." menu next to other apps. But when I tap exactly the same file from my app folder on iCloud, my app is not listed in "Import with ..." menu.

To clarify what I mean by saying my app folder on iCloud. App has a functionality to export and save certain data on iCloud with the following function:

func autoExportToIcloudDrive(_ localFileURL:URL, fileNameST:String) {
        let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents").appendingPathComponent("\(fileNameST).csv");
        if iCloudDocumentsURL != nil {
            let olderFileURL = iCloudDocumentsURL?.appendingPathComponent(fileNameST);
            if FileManager.default.fileExists(atPath: olderFileURL!.path) {
                self.uniFunc.deleteFileAtPath(pathUrl: olderFileURL!);
            }
            do {
                try FileManager.default.copyItem(at: localFileURL, to: iCloudDocumentsURL!);
            } catch {
                let nserror = error as NSError;
                fatalError("\(nserror), \(nserror.userInfo)");
            }
        }
    }

This creates app folder in iCloud drive and stores my file there. And when I tap on this file I cannot see my app in "Import with ..." menu. When I move file out of app folder my app appears in "Import with ..." menu.

Is this an intended design and apps are not expected to "see" files in their own iCloud drive folders or I am missing some kind of additional file association in .plist file?

1

There are 1 answers

1
Rein Spijkerman On

This is intended behaviour, as "importing" is different from "opening". By importing a file, you can make its contents part of your apps data. Files in your apps iCloud container already are (part of) your apps data, so importing them into your apps data makes no sense.

UPDATE

The following properties under CFBundleDocumentTypes will have effect on if and how your app is presented in the context of a file:

  • The value of CFBundleTypeRole: "Editor" vs. "Viewer" -- persisting edits requires importing the file into the apps data ("Default" is not a valid value here)
  • Assigned LSHandlerRank: "Owner", "Default", "Alternate" -- declaring to be the primary app (owner) for a file type could lead to the "Import with" part being dropped
  • Registering for the correct LSItemContentTypes: ".csv" files will be recognised as "public.comma-separated-values-text" (kUTTypeCommaSeparatedText)