简体   繁体   中英

Cannot programmatically access some files in iCloud Drive

This may be my solution

I suspect that my problem occurs because I did not turn on "iCloud" capabilities but since I have a free developer account I cannot do that.

If turning on "iCloud" capabilities is the solution, is there also some documentation which states this ?

I only found documentation regarding "CloudKit" which never refers to "iCloud Drive".

On this website there are some links to additional documentation.


Problem statement

Folder structure in iCloud Drive:

  • "TestApp" (directory with the name of the app in iCloud Drive)
    • "test" (directory)
      • "testFile 1.txt" (open document using UIDocumentBrowserViewController )
      • "testFile 2.txt" (trying to open document programmatically)

If I open a document in a directory using UIDocumentBrowserViewController ( documentation ) I can call document.open(...) without problems ( document is a UIDocument subclass). However if I want to programmatically access the other file in the folder there is an error:

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"}}

How I try to programmatically access "testFile 2.txt"

When the user opens "testFile 1.txt" I get the url of it ie:

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

Now I'm using the following code to try to access "testFile 2.txt" (see also inline comments):

// 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`

As you can see "testFile 2.txt" 'does not exist' for the file manager.

Consider an analogy:

You are a guest in someone's home. You ask for some water. They take a bottle from the fridge and give it to you.

Does that mean that they have given you permission to go to the fridge and take a beer or bottle of wine? No. Does it imply permission to search through the contents of their fridge to see what they have? No. Can you ask explicitly for a beer? Yes. Can they say "No"? Also yes.

Similarly, your app is a guest on the user's device. It operates in a sandbox. It needs to ask for permission to access resources outside the sandbox.

In the case of file access it needs specific permission for the file it wants to access. It can't just create a file path and access a file; The user needs to specifically grant permission to access a file.

In this case the permission is granted via the UIDocumentBrowserViewController . Your app was not granted access to testFile 2.txt so iOS acts as if that file doesn't exist. If you want access to that file you have to ask explicitly.

There is no capability for an app to access the complete contents of a user's files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM