1

除了打开和保存自己的自定义文档之外,我的基于 iOS 11 文档浏览器的应用程序应该能够导入适当格式的文本文件并将其转换为自己的文档。

但是,当在文档浏览器中选择文本文件时,只有当所选文件在本地存储中时,应用程序才能访问其内容(然后执行转换),但当文件存储在 iCloud 中时无法访问内容.

下面提供了我用于documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentURLs documentURLs: [URL])委托方法的代码的简化注释版本:

func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentURLs documentURLs: [URL]) {

    guard let sourceURL = documentURLs.first else { return }

    // Check extension to verify if it is a custom document
    if sourceURL.pathExtension == "mydoc" {

        // If it is a custom document, we present it directly
        // (the presentDocument method is a standard implementation from Apple docs)
        presentDocument(at: sourceURL)

    } else {

        // Otherwise, we suppose the file is a text file to be imported
        // We first create a new document, then try to import the contents of the text file     
        let url = FileManager().temporaryDirectory.appendingPathComponent("New Document").appendingPathExtension("mydoc")
        let doc = MyDocument(fileURL: url)

        do {
            let textFileContents = try String(contentsOf: sourceURL)
            // It works fine if the text file is in local storage
            // Here the document model is updated by converting the contents of the text file 
            // (code omitted, it is actually a method in the MyDocument class)
            // ...
        } catch {
            // Produce error message: cannot access text file
            // The error message is always produced if the text file is in iCloud storage!
        }

        // Save and close the document with standard code, e.g.:               
        doc.save(to: url, for: .forCreating) { (saveSuccess) in
            guard saveSuccess else { return }
            doc.close(completionHandler: { (closeSuccess) in
                guard closeSuccess else { return }  
            })

        // Reveal and import the document
        self.revealDocument(at: url, importIfNeeded: true) { (revealedDocumentURL, error) in
           if let error = error {
               // Handle the error appropriately
               return
           }
           // Present the Document View Controller for the revealed URL
           self.presentDocument(at: revealedDocumentURL!)
        }
    }
}

info.plist 文件将自定义文档和 public.text 声明为文档类型(具有适当的角色和处理程序等级),并将自定义文档声明为导出的 UTI。如果选择的文件是自定义文档,则一切正常,无论文件是本地文件还是 iCloud 中。

由于文件在本地存储中时导入工作,我认为这可能是 iCloud 权限的问题,即使 Apple 文档的UIDocumentBrowserViewController状态:

系统自动为您处理对 iCloud 的访问;您不需要启用应用程序的 iCloud 功能。

但是,尝试将 iCloud 功能添加到我的应用程序的权利并没有解决问题(实际上使情况变得更糟,因为现在完全相同的代码正在将新创建的文档保存在应用程序的默认 iCloud 容器中,这不是文档浏览器使用相同的 iCloud Drive 位置,以便所有文档对浏览器“不可见”-但我离题了...)。

另一个“有趣”的元素是我还在UIDocumentPickerViewController应用程序中实现了一个将附加内容从文本文件导入到已经打开的自定义文档中。我使用的代码与上面的基本相同......并且它完美地工作,与文本文件是在本地存储还是在 iCloud 中无关!这可以强化这种观点,即问题与UIDocumentBrowserViewController.

所以,总而言之:我可以做些什么来访问存储在 iCloud 中的文本文件的内容并将它们转换为我的应用程序的自定义文档?提前感谢您的任何建议(如果问题的表述有问题,请保持温和 - 这是我潜伏数月后的第一个 stackoverflow 问题!)。

4

2 回答 2

2

我不是 100% 确定,但我相信您需要调用startAccessingSecurityScopedResource该 URL 来使用文档浏览器提供给您的沙盒扩展。完成后不要忘记调用stopAccessing,以免泄漏内核资源。此外,如果您不是真的在编辑该文档,您可能正在寻找一个UIDocumentPickerViewController代替?用户打开一个文件然后最终编辑另一个文件很奇怪。启动一个新文档,然后使用选择器将文本文件导入其中不是更好的 UX 吗?

于 2018-04-11T07:34:07.723 回答
0

插入式小片段:(Swift 5.x)

    public func documentBrowser(_ controller: UIDocumentBrowserViewController,
                                  didPickDocumentsAt documentURLs: [URL]) {

            dismiss(animated: true, completion: nil)

            self.importAll(urls: documentURLs)
        }



    final func importAll(urls: [URL]) {

        //TODO: use timer/loop/async stuff..
        // for multiple files..

        urls.forEach { (url: URL) in

            let secured = url.startAccessingSecurityScopedResource()

            = myImportInSessionFrom(url: url)

            if secured { url.stopAccessingSecurityScopedResource() }

        }
 }
于 2020-01-31T11:16:12.283 回答