为什么 url.bookmarkData 返回零?

Why is url.bookmarkData returning nil?

我们有一个 UIDocumentPickerViewController 的实现,看起来像这样:

case .openInitialization:
    // Setup UIDocumentPicker.
    if #available(iOS 14, *) {
        documentsPicker = UIDocumentPickerViewController(forOpeningContentTypes: [
            UTType.text,
            UTType.utf8PlainText,
            UTType.flatRTFD,
            UTType.pdf])
    } else {
        documentsPicker = UIDocumentPickerViewController(documentTypes: [
            String(kUTTypeText),
            String(kUTTypeUTF8PlainText),
            String(kUTTypeFlatRTFD),
            String(kUTTypePDF)], in: .open)
    }

一切正常,我们可以 select 一个文档。当我们 select 一个文档时,我们得到一个文档 url 但在某些情况下(尤其是在一个驱动器上),当我们想要将 url 变成书签时会遇到问题。以下代码 returns nil:

guard let bookmark = try? url.bookmarkData(options: .minimalBookmark, includingResourceValuesForKeys: nil, relativeTo: nil) else { return }

有人知道为什么会这样吗?或者我们可以做些什么来让它在没有 returning nil 的情况下工作?

编辑:

我们已尝试添加 try catch,但出现了以下错误,但没有太大帮助:Error Domain=NSCocoaErrorDomain Code=260(文件不存在)。

编辑 2:

因此,如果我直接从存档中打开到我们的应用程序,则完全没有问题。但是我们仍然需要从 UIDocumentPickerViewController 开始工作。

此外,出于某些原因,以这种方式解锁的文件之后将只能在 UIDocumentPickerViewController 中使用。

文件也可以从 onedrive 打开,然后在另一个应用程序(我们的)中打开。但这并没有给出文件不存在的错误。

编辑 3: 所以我已经测试并阅读了大量内容。我可以看出,对于 documentpicker 选择的某些文件,以下内容 return 为 false:

var exist = FileManager.default.fileExists(atPath: url.path)

但是,如果我只从 iOS 存档应用程序打开文件一次,它将在之后完美运行。如果有某种方法可以像苹果那样告诉它 update/download。

编辑 4: 我在 github 做了一个示例项目来演示这个问题。

我在这里回答了一个类似的问题:

你能检查一下将你的 url 包装在安全访问范围内是否有帮助吗?:

url.startAccessingSecurityScopedResource()
print(FileManager.default.fileExists(atPath: url.path))
url.stopAccessingSecurityScopedResource()

以上应该打印正确。这是因为这些 API 访问应用程序沙箱之外的文件。

参见:https://developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories

使用了 apple 的技术票,他们提供了解决方案 :D

NSFileCoordinator().coordinate(readingItemAt: url, options: .withoutChanges, error:&err, byAccessor: { (newURL: URL) -> Void in
  do {
    let bookmark = try newURL.bookmarkData()
  } catch let error {
    print("\(error)")
  }
})

if let err = err {
  print(err.localizedDescription)
}