0
votes

I have a problem sharing files between the OSX version of my app and the iOS version of the app when saving into the shared iCloud folder.

The iMac version can read any file from the shared folder. However the iOS version fails to read files saved from the OSX version.

When calling contentsOfDirectory on iOS

FileManager.default.contentsOfDirectory(at: mmFile.containerUrl!, includingPropertiesForKeys: nil, options: [])

I get Urls back like:

file:///private/var/mobile/Library/Mobile%20Documents/iCloud~xxx/Documents/Untitled.render-z, file:///private/var/mobile/Library/Mobile%20Documents/iCloud~xxx/Documents/.refract.render-z.icloud

Where the first file was saved on iOS and loads correctly, the second from OSX which has a "." prefix and a ".icloud" postfix and cannot be loaded.

I save the files with the same code:

stringData.write(to: url(), atomically: true, encoding: .utf8)

The encoding does not matter, its the same behavior if I use .ascii or .utf8 etc.

When I try to read such a file in iOS I get content back like

bplist00Ó\NSURLNameKey_NSURLFileSizeKey_NSURLFileResourceTypeKey_2spheres.render-z

I cannot figure this out! All the entitlements and plist properties seem to be correct and sharing the iCloud DB works fine too.

1
What file name did you actually use when creating the file from OSX, and what content do you expect to see? The file .refract.render-z.icloud is a hidden file which looks like some kind of metadataDale
It's a string with encoded JSON which serialized the project state. I use the same code to read / write the String content and it works fine in all cases, except for reading the files created on OSX on iOS. I can read the same file w/o problems on OSX and it's not displayed as hidden.Markus Moenig

1 Answers

0
votes

I figured it out. For anybody who had the same problem:

Don't use the FileManager to parse file but use NSMetadataItem's like this

    query = NSMetadataQuery()
    query.predicate = NSPredicate.init(format: "%K BEGINSWITH %@", argumentArray: [NSMetadataItemPathKey, self.containerUrl!.path])
    query.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]

    NotificationCenter.default.addObserver(self, selector: #selector(self.updateCloudData), name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil)

    query.enableUpdates()
    query.start()

and most importantly use the FileController to read the file, this ensures synchronization with iCloud:

func loadJSON(url: URL) -> String
{
    var string : String = ""

    let fc = NSFileCoordinator()
    fc.coordinate(readingItemAt: url, options: .forUploading, error: nil, byAccessor: { url in
        do {
            string = try String(contentsOf: url, encoding: .utf8)
        } catch {
            print(error.localizedDescription)
        }
    })
    return string
}