温馨提示:本文翻译自stackoverflow.com,查看原文请点击:swift - Cannot access/import contents of iCloud file picked in iOS 11 document browser
ios swift icloud icloud-drive uidocumentbrowservc

swift - 无法访问/导入在iOS 11文档浏览器中选择的iCloud文件的内容

发布于 2020-04-07 10:09:15

除了打开和保存自己的自定义文档,基于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都声明为文档类型(具有适当的Role和Handler等级),并将自定义文档声明为Exported UTI。如果选择的文件是自定义文档,则无论文件是本地文件还是在iCloud中,一切都可以正常工作。

由于导入是在文件位于本地存储中时进行的,因此我认为这可能是iCloud权限的问题,即使Apple文档显示了UIDocumentBrowserViewController状态:

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

然而,想到iCloud功能添加到我的应用程序的权利都没有解决的问题(实际上使病情加重,在这个意义上完全相同的代码现在被保存在应用程序的默认的iCloud容器新创建的文档,这是没有的文档浏览器使用的iCloud Drive位置相同,因此所有文档对浏览器都是“不可见的-但我离题了...”。

另一个“有趣”的元素是,我还在UIDocumentPickerViewController应用程序中实现了,以将其他内容从文本文件导入到已经打开的自定义文档中。我使用的代码与上面的代码基本相同...并且完美运行,无论文本文件是在本地存储还是在iCloud中!这可能会增强以下观点:该问题与的特定权限问题有关UIDocumentBrowserViewController

因此,总而言之:我该怎么做才能访问存储在iCloud中的文本文件的内容并将其转换为我的应用程序的自定义文档?预先感谢您的任何建议(如果问题的表述有问题,请多加礼貌-这是我潜伏数月后的第一个stackoverflow问题!)。

查看更多

提问者
emime
被浏览
11
3,653 2019-01-24 11:52

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