iosswiftcloudkiticloud-drive

Failing to write to iCloud Drive


I'm having an hard time with iCloud Drive in my app. I cannot create my app's folder in iCloud Drive.

Somehow, yesterday, I managed to create the folder and save items there, but today, after I run my code, the folder is gone and I cannot save files anymore.

Here's a sample code that I have managed to run and put to work yesterday:

let str = "ivan cantarino"

guard let iCloudPath = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents") else {
    print("Failed to get iCloud path")
    return
}

print("icloud path:", iCloudPath.absoluteString)
// prints: icloud path: file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~ivancantarino~Cozynote/Documents

let lastPath = iCloudPath.appendingPathComponent("iCloudDrive.txt")

// writes a file to the directory
do {
    try str.write(to: lastPath, atomically: true, encoding: .utf8)
    print("success")
} catch {
    print("failed to write with error:", error.localizedDescription)
    // prints: failed to write with error: The file “iCloudDrive.txt” couldn’t be saved in the folder “Documents”.
}

Here's my info.plist iCloud info:

<key>NSUbiquitousContainers</key>
<dict>
    <key>iCloud.com.ivancantarino.Cozynote</key>
    <dict>
        <key>NSUbiquitousContainerIsDocumentScopePublic</key>
        <true/>
        <key>NSUbiquitousContainerName</key>
        <string>Cozynote</string>
        <key>NSUbiquitousContainerSupportedFolderLevels</key>
        <string>Any</string>
    </dict>
</dict>

Here's a print, showing that I'm using the proper container:

image

I have bumped the app's version and build number, reinstalled the app, but somehow I cannot write to the path. It keeps printing the error.

Can anyone spot anything I'm doing wrong here?


Solution

  • I've worked on an app that depends heavily on iCloud drive , Bottom line it's the worst . hard to debug unpredictable and poorly documented .

    So i can give you a couple of options to try and see if it helps . One of the things that could greatly help you is creating UIDocument SubClass , these can talk pretty well with iCloud Drive.

     class TextDoc:UIDocument{
        var data:String?
    
    
        override func contents(forType typeName: String) throws -> Any {
            return data?.data(using: .utf8) ?? Data()
        }
    
        override func load(fromContents contents: Any, ofType typeName: String?) throws {
            if let userContent = contents as? Data {
                data = String(data: userContent, encoding: .utf8)
            }
        }
    
    }
    
    
    let folder = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Folder")
    
    try? FileManager.default.createDirectory(atPath: folder?.path ?? "", withIntermediateDirectories: true, attributes: nil)
    
    let fileURL = folder?.appendingPathComponent("iCloudDrive.txt")
    
    let uiDoc = TextDoc(fileURL: fileURL!)
    uidoc.save(to: url, for: .forOverwriting) { (success) in
        print("save was \(success)")
    }
    

    If the saving was successful you can open it using open(completionHandler: <#T##((Bool) -> Void)?##((Bool) -> Void)?##(Bool) -> Void#>)

    Also make sure you've iCloud Set correctly in developer.apple.com enter image description here