Export UIDocument with custom file package UTI

I'm trying to export my

UIDocument
subclass with a
UIDocumentPickerViewController
. The subclass writes data to a
FileWrapper
and its UTI conforms to
com.apple.package
.


But the presented document picker shows "Documents in iCloud Drive are not available because the iCloud Drive setting is disabled."


The document is successfully written to the cache, as I can see from the exported container package.


When I change the document subclass and custom UTI to conform to a single file (e.g.

public.plain-text
), the document picker works fine and I can export the file. So the problem seems to be with the Document Type or Exported UTI.


Am I doing something wrong or is this a bug?



Info.plist

<key>CFBundleDocumentTypes</key>
<array>
  <dict>
    <key>CFBundleTypeIconFiles</key>
    <array/>
    <key>CFBundleTypeName</key>
    <string>Custom Doc</string>
    <key>LSHandlerRank</key>
    <string>Owner</string>
    <key>LSItemContentTypes</key>
    <array>
      <string>com.zxzxlch.documentsandbox.customdoc</string>
    </array>
    <key>LSTypeIsPackage</key>
    <true/>
  </dict>
</array>

  ...

  <key>UTExportedTypeDeclarations</key>
<array>
  <dict>
    <key>UTTypeConformsTo</key>
    <array>
      <string>com.apple.package</string>
    </array>
    <key>UTTypeDescription</key>
    <string>Custom Doc File</string>
    <key>UTTypeIdentifier</key>
    <string>com.zxzxlch.documentsandbox.customdoc</string>
    <key>UTTypeTagSpecification</key>
    <dict>
      <key>public.filename-extension</key>
      <array>
        <string>zzz</string>
      </array>
    </dict>
  </dict>
</array>



CustomDocument.swift


private let textFilename = "contents.txt"

class CustomDocument: UIDocument {
    var content = "Test"

    override func load(fromContents contents: Any, ofType typeName: String?) throws {
        guard let topFileWrapper = contents as? FileWrapper,
            let textData = topFileWrapper.fileWrappers?[textFilename]?.regularFileContents else {
                return
        }
        content = String(data: textData, encoding: .utf8)!
    }

    override func contents(forType typeName: String) throws -> Any {
        let textFileWrapper = FileWrapper(regularFileWithContents: content.data(using: .utf8)!)
        textFileWrapper.preferredFilename = textFilename

        return FileWrapper(directoryWithFileWrappers: [textFilename: textFileWrapper])
    }

}


ViewController.swift


func exportDocument() {
    // Write to cache
    let cachesDir = FileManager.default.urls(for: FileManager.SearchPathDirectory.cachesDirectory, in: .allDomainsMask).first!
    let dataDir = cachesDir.appendingPathComponent("export", isDirectory: true)
    try! FileManager.default.createDirectory(at: dataDir, withIntermediateDirectories: true, attributes: nil)


    let fileURL = dataDir.appendingPathComponent("cookie").appendingPathExtension("zzz")


    let archive = CustomDocument(fileURL: fileURL)
    archive.content = "Cookie cat"


    archive.save(to: archive.fileURL, for: .forCreating) { success in
        guard success else {
            let alertController = UIAlertController.notice(title: "Cannot export data", message: nil)
            self.present(alertController, animated: true, completion: nil)
            return
        }

        let documentPicker = UIDocumentPickerViewController(url: archive.fileURL, in: .exportToService)
        documentPicker.delegate = self
        self.present(documentPicker, animated: true, completion: nil)
    }

}

I'm seeing this as well. Did you ever find a solution to this problem? If I export to a single-file file format, it works fine.


Also, the Dropbox app extension doesn't seem to handle custom package file formats. And when I email the resultant document, what I seem to receive on the other end of the email is a zip compressed version of the package (without the .zip extension added — I have to do this myself to unzip it).

Export UIDocument with custom file package UTI
 
 
Q