无法编程访问iCloud Drive中的某些文件。

3

这可能是我的解决方案

我怀疑我的问题出在没有打开 "iCloud" 功能上,但由于我只有一个免费的开发者账户,所以无法这样做。

如果打开 "iCloud" 功能是解决方案,是否还有一些说明文件可以说明这一点

我只发现了关于 "CloudKit" 的文档,但从来没有提到 "iCloud Drive"。

在这个网站上有一些链接到其他文档的链接。


问题陈述

iCloud Drive 中的文件夹结构:

  • "TestApp"(iCloud Drive 中应用程序名称的目录)
    • "test"(目录)
      • "testFile 1.txt"(使用 UIDocumentBrowserViewController 打开的文档)
      • "testFile 2.txt"(尝试通过编程方式打开文档)

如果我使用 UIDocumentBrowserViewController文档)打开目录中的文档,我可以毫无问题地调用 document.open(...)documentUIDocument 子类)。然而,如果我想以编程方式访问文件夹中的其他文件,则会出现错误:

Error Domain=NSCocoaErrorDomain Code=257 "The file “testFile 2.txt” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/TestApp/test/testFile 2.txt, NSUnderlyingError=0x2829d20a0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

我如何尝试编程访问 "testFile 2.txt"

当用户打开 "testFile 1.txt" 时,我会获取它的 URL,即:

"file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/TestApp/test/testFile%201.txt"

现在我正在使用以下代码尝试访问“testFile 2.txt”(请参见内联注释):

// I get this url from the delegate method `UIDocumentBrowserViewControllerDelegate.documentBrowser(_:didPickDocumentsAt:)`
let file1URL = // ...
let file2URL = file1URL
    .deletingLastPathComponent()
    .appendingPathComponent("testFile 2")
    .appendingPathExtension("txt")

let success = file2URL.startAccessingSecurityScopedResource() // returns `false`

TestDocument(fileURL: file2URL).open{ success in
    print(success) // prints `false` and see ERROR above
}

// checking existence
let fm = FileManager.default
fm.isUbiquitousItem(at: file1URL)    // returns `true`
fm.fileExists(atPath: file1URL.path) // returns `true`
fm.isUbiquitousItem(at: file2URL)    // returns `false`
fm.fileExists(atPath: file2URL.path) // returns `false`

正如您所看到的,对于文件管理器来说,“testFile 2.txt”“不存在”。

1个回答

1
考虑一个类比:
你是别人家的客人。你要求喝点水,他们从冰箱里拿了一瓶给你。
这是否意味着他们允许你去冰箱里拿啤酒或葡萄酒?不是的。这是否暗示你可以搜索他们冰箱里的内容?也不是的。你可以明确地要求一瓶啤酒吗?可以。他们可以说“不”吗?当然可以。
同样地,你的应用程序是用户设备上的客人。它在沙盒中运行。它需要请求许可才能访问沙盒外的资源。
在文件访问的情况下,它需要特定的权限来访问它想要访问的文件。它不能只是创建一个文件路径并访问一个文件;用户需要明确授权才能访问文件。
在这种情况下,通过 UIDocumentBrowserViewController 授予了权限。你的应用程序没有被授予访问 testFile 2.txt 的权限,因此 iOS 就像那个文件不存在一样。如果你想访问该文件,你必须明确地请求许可。
应用程序无法访问用户文件的全部内容。

谢谢您提供这个很好的比喻!但是我认为应用程序目录(这里是“TestApp”)也在沙盒内部,对吗?那么所有iCloud Drive文件都在应用程序沙盒之外吗? - Qbyte
所有iCloud文件(以及Dropbox文件、OneDrive文件和任何由文件提供者提供的文件)都在沙盒之外。当您使用文档浏览器时,iOS会授予您对该文件的许可;您必须使用startAccessingSecurityScopedResource来行使该权限。 - Paulw11
你在iCloud Drive中创建了名为“TestApp”的目录。如果你想的话,你也可以将该目录命名为“Fridge”,只要你被授予权限,仍然可以访问它。仅仅因为应用程序和文件夹具有相同的名称,并没有隐含的访问权限。 - Paulw11
你能在回答中也写一下吗?我还有点困惑:请参见 https://developer.apple.com/library/archive/documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html#//apple_ref/doc/uid/TP40012094-CH6-SW13。他们只提到了“iCloud容器”。这是否与“TestApp”目录相同?如果是的话,那么就必须激活iCloud功能。 - Qbyte
不,iCloud容器是一个应用程序可以使用的私有存储库,用于在用户设备之间同步文档和键值存储。iCloud容器对应用程序可见,无需任何其他权限,因为它们被视为应用程序的数据。用户不能使用文件应用程序查看iCloud容器的内容,也不能直接修改其内容。 - Paulw11
iCloud容器可以拥有一个文档文件夹,并通过“文件”应用程序向用户显示此文件夹。 - pre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接