iosicloudnsfilemanagernsfilecoordinator

Copy iCloud file to sandbox


I'm looking for a better way to download a bunch of files from my iCloud container to my sandbox. This is what I currently use:

for (FileAttachments *fileLink in items) {
        NSURL *cloudFileURL = [fileLink urlForCloudAttachmentWithName];

        NSURL *fileURL = [backupCloudLocalDirectoryURL URLByAppendingPathComponent: fileLink.fileName];

        NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];

        [fileCoordinator coordinateReadingItemAtURL:fileURL options:NSFileCoordinatorReadingWithoutChanges error:&error

                                             byAccessor:^(NSURL *newURL) {

                   NSError *blockError = nil;

                   [fileManager copyItemAtURL:cloudFileURL toURL:fileURL error:&blockError];
                                }];
        }
}

Is there any problem with making a copy of the iCloud item this way? In production, I have some users complaining that all their files weren't downloaded. Is it better to use NSFileManager's startDownloadingUbiquitousItemAtURL:error instead? If so, why? Thanks.


Solution

  • It's still not completely clear to me from comments how you're discovering the URLs, however some important details that affect your situation are:

    1. Using coordinateReadingItemAtURL:block: has nothing to do with downloading files from iCloud. The purpose of NSFileCoordinator is to coordinate among readers and writers of a file so that, for example, you don't get two threads trying to write to the same file at the same time. You use file coordinators with iCloud because the iCloud system needs to read and write files and so does your app. Using a coordinator avoids corrupting the file, but again, has nothing to do with downloading the file.

    2. To download a file from iCloud you need to use startDownloadingUbiquitousItemAtURL:error: and then wait until the file downloads. The normal flow here is:

      a. Use NSMetadataQuery to find files that exist in the iCloud account

      b. Use startDownloadingUbiquitousItemAtURL:error: to make sure they're available on the local device.

      The reason you need to use this call is simply because that's how iCloud works on iOS. Files don't download until you ask them to download, and this is how you ask. [On OS X it's different, everything automatically downloads.]

    3. You cannot simply copy from an iCloud URL to another location unless you already know that the file has been downloaded. The file-copy operation does not download the file, so if the file isn't available locally, the copy will fail.