除了打开和保存自己的自定义文档,基于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问题!)。
我不确定100%,但是我相信您需要调用startAccessingSecurityScopedResource
该URL才能使用文档浏览器提供给您的沙盒扩展名。完成操作后不要忘记调用stopAccessing
,以免泄漏内核资源。另外,如果您不是真正在编辑该文档,那么您可能正在寻找一个UIDocumentPickerViewController
替代?用户打开文件然后编辑另一个文件很奇怪。启动新文档,然后使用选择器将文本文件导入其中是否是更好的UX?
非常感谢,它奏效了!
startAccessingSecurityScopedResource
在import函数之前调用就可以了。我在link上看到了您的答案,但将注意力集中在书签部分(无效),而不是开始/停止访问部分。关于您的问题,我的确也实现了UIDocumentPickerVIewController
,但是由于我的应用程序的所有文档都需要从csv文件(由另一个应用程序生成)开始,因此我认为仅在文档浏览器中选择它们以启动新文件就很有用。文献。