UTI and UIDocumentBrowserViewController

It seems I do not understand correctly how the UTI and UIDocumentBrowserViewController are related. When I modify the Info.plist's 'CFBundleDocumentTypes' key, it seems that the following function no longer gets called when tapping the '+' button:


func documentBrowser(_ controller: UIDocumentBrowserViewController, didRequestDocumentCreationWithHandler importHandler: @escaping (URL?, UIDocumentBrowserViewController.ImportMode) -> Void)  


'Specifically, I am using the Document Based App template, made no changes to the code, only changed 'public.image' to 'com.mycompany.mytype' as the first item in the 'LSItemContentTypes' array.


So it seems I am in need of some documentation about how these keys affect the UIDocumentBrowserViewController, both in my app and in other 3rd party apps. I read the following, but it was of no help:

https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/DocumentInteraction_TopicsForIOS/Articles/RegisteringtheFileTypesYourAppSupports.html


Is there proper documentation on exactly how this works and how to set up a project?


(As a side-problem I would like to use UIManagedDocument, but exactly how to set up a document based app using UIManagedDocument is also unclear. WWDC sessions seem to become more and more superficial each year, so those are unfortunately not of any help.)

If you want to use "com.mycompany.mytype" as your document UTI, you must also provide an "exported UTI" definition, as well as the document type definition. (In specific scenarios, you provide an "importedUTI" instead, but if the UTI is the type of your app's documents, an exported UTI is the correct to provide).

Thank you for your suggestion. I tried what you said, but to no avail: the documentbrowser shows the plusbutton, but tapping it does not lead to the delegate callback being called.

Here are screenshots of how I've set it up:

https://ibin.co/3UDvd5GYAYQ3.png

https://ibin.co/3UDvpsvMYpA0.png


Or in code:

<key>CFBundleDocumentTypes</key>
<array>
   <dict>
      <key>CFBundleTypeIconFiles</key>
      <array/>
      <key>CFBundleTypeName</key>
      <string>MyType</string>
      <key>CFBundleTypeRole</key>
      <string>Editor</string>
      <key>LSHandlerRank</key>
      <string>Owner</string>
      <key>LSItemContentTypes</key>
      <array>
         <string>com.mycompany.mytype</string>
      </array>
  </dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
   <dict>
      <key>UTTypeDescription</key>
      <string>MyType</string>
      <key>UTTypeIdentifier</key>
      <string>com.mycompany.mytype</string>
   </dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
  <dict>
      <key>UTTypeDescription</key>
      <string>MyType</string>
      <key>UTTypeIdentifier</key>
      <string>com.mycompany.mytype</string>
  </dict>
</array>


It seems this should not be so unclear, and I am missing some obvious documentation. But where to find it?

>> where to find it?


https://developer.apple.com/library/content/documentation/DataManagement/Conceptual/DocumentBasedAppPGiOS/DocumentImplPreflight/DocumentImplPreflight.html


You doing a couple of things wrong:


— There's no need to provide an Imported UTI declaration for the same identifier as the Exported UTI. (You export UTIs belonging the the app. You import UTIs belonging to other apps.)


— You must provide a file extension for the exported UTI. In iOS and macOS, the UTI is not stored as file metadata, but is derived from the file extension. (This is silly, but it works that way for historical reasons.) Without an extension, the browser can't determine the file type.


— You must declare a conformance for the exported UTI. If it's a simple file, declare it to conform to "public.data". If it's a file package, declare it to conform to "com.apple.package".

""Thank you again Quincy for you help. I'm still not getting it to work though.


Here is part of my plist after I have very slightly edited it. This plist still makes the + button call the callback.

However, when I change the 'public.image' to anything else (e.g. 'myType', 'public.myType' or 'private.myType'), the plusbutton will no longer make the callback.

As you can see, the template makes the plist include the 'LSItemContentTypes' key. Here is what the docs say on this:


This key contains an array of strings. Each string contains a UTI defining a supported file type. The UTI string must be spelled out explicitly, as opposed to using one of the constants defined by Launch Services. For example, to support PNG files, you would include the string “

public.png
“ in the array. When using this key, also add the
NSExportableTypes
key with the appropriate entries. In macOS 10.5 and later, this key (when present) takes precedence over these type-identifier keys:
CFBundleTypeExtensions
,
CFBundleTypeMIMETypes
,
CFBundleTypeOSTypes
.


<key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeIconFiles</key>
            <array/>
            <key>CFBundleTypeName</key>
            <string>My Name</string>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>LSHandlerRank</key>
            <string>Owner</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.image</string>
            </array>
        </dict>
    </array>



So, as per the docs, I include the '

NSExportableTypes'
key, make sure it has 'myType' as a string, and the plist looks like this:
    <key>NSExportableTypes</key>
    <array>
        <string>myType</string>
    </array>
    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeIconFiles</key>
            <array/>
            <key>CFBundleTypeName</key>
            <string>My Name</string>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>LSHandlerRank</key>
            <string>Owner</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.myType</string>
            </array>
        </dict>
    </array>


Again, the plus button does not call the callback. Using various other names for the type also does not make the plus button make the callback (e.g. 'public.myType', 'private.myType', 'myType' etc).

You said "You must provide a file extension for the exported UTI.". This might be the thing that will help me, but how to do this? And still, where to find good documentation on this, I am a bit hesitant to start building an app based on something I do not understand very well.


Thank you again for your help!


Edit:

I just took a look at :https://developer.apple.com/library/content/documentation/DataManagement/Conceptual/DocumentBasedAppPGiOS/DocumentImplPreflight/DocumentImplPreflight.html


However, the Xcode UI has changed, and no longer does it contain an option to set the 'Extensions'. This link also does not mention how to manually put this into the plist. So again, it seems like I am in need of accurate documentation.

So the anser two my original question was to include 'public.content, com.apple.package' in the 'Conforms To' field in Xcode.

The next problem is that the UIDocumentBrowserViewController does not work well with UIManagedDocument's package-type files. I've filed a bug for this.


I get the feeling that the UIDocumentBrowserViewController and the Files app is not anywhere near production level at all, and it would be very unwise to build an app on such flaky foundations.

I've still got iCloud/Core Data problems vividly in my mind, whcih I feel resembles very much the current state of how Files are handles in iOS 11. So I will avoid UIDocumentBrowserViewController and move on, so I can avoid pooring a lot of time into something that just is not going to work anytime soon. Maybe iOS 12 will be the release that has a decent UIDocumentBrowserViewController and file handling, iOS 11 seems not like a wise choice right now.


Thanks for you help!

I'm having a similar problem, where I have a + button on my UIDocumentBrowserViewController, but my "didRequestDocumentCreationWithHandler" delegate method is never called.


I noticed that one of the links you gave uses "UITypeIdentifier", whereas other documentation says "UTTypeIdentifier". (read it real close). So I wonder if maybe Apple's documentation was simply never QA'd to see if it was right? What else did they forget?


However... I did copy my doc & export definitions from a working mac app (and clicking the New Document button in the UIKitForMac version of my app works!), and then painstakingly spent hours trying to find documentation for how to modify the the docs types & export types to work for iOS.


Did you ever figure out how to make document-based apps work?

UTI and UIDocumentBrowserViewController
 
 
Q