将文件移出尚未完全下载的iCloud时丢失数据(未报告错误)

时间:2014-03-25 15:01:10

标签: macos cocoa icloud nsfilemanager

我有一个带有iCloud集成的Mac应用程序。它不是基于NSDocument,我通过[NSFileManager setUbiquitous:…]自己处理移入和移出iCloud的文件。这就是我遇到的:

  1. 我在连接到iCloud
  2. 时向我的应用添加了一个大的(15 MB)文档
  3. 等待文档完全上传到iCloud
  4. 现在我在Mac上退出了我的iCloud帐户→该文件已从Mac中删除
  5. 我打开了我的应用,重新登录iCloud,文件出现在磁盘上
  6. 很快,通过我的应用程序,我将所有文件从iCloud移到本地磁盘(内部使用[NSFileManager setUbiquitous:NO…]
  7. 大文件没有被复制到本地磁盘(我怀疑因为它还没有从iCloud 100%下载),但它也从iCloud中消失了。无法恢复数据。 NSFileManager报告没有错误。

    以下是相关代码:

    NSArray *files = [fileManager contentsOfDirectoryAtURL:iCloudDataFolderURL
                                includingPropertiesForKeys:nil options:0 error:&error];
    
    for (NSURL *fileURL in files) {
        // figure out URLs […]
        if (![fileManager setUbiquitous:NO 
                              itemAtURL:iCloudFileURL 
                         destinationURL:localDocumentURL 
                                  error:&error]) {
            hadError = YES;
            NSLog(@"Error moving file from iCloud: %@ to local storage: %@ Error: %@",
                   iCloudFileURL, localDocumentURL, error);
        }
    }
    

    如果文件不完全在本地磁盘上,我本来期望对[NSFileManager setUbiquitous:NO…]的调用阻塞或失败。相反,我最终得到一个文件包装器,在Finder中显示15 MB的文件大小,但实际上是空的。

    将文档从iCloud移出到本地磁盘的安全方法是什么?

1 个答案:

答案 0 :(得分:0)

您可以使用NSFileCoordinator和NSFileManager方法移入和移出文件。我不知道它是否更安全,但它可以让你更好地控制错误状况以及出现问题时会发生什么。

举个例子,看一下Ensembles框架here的iCloud后端(Disclosure:这是我的项目)。搜索uploadLocalFile:...downloadFromPath:...。它们是特别先进的方法,有超时,但想法是一样的。

首先,创建一个文件协调器。

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

然后复制或移动文件。

    [coordinator coordinateReadingItemAtURL:fromURL options:0   
        writingItemAtURL:toURL 
        options:NSFileCoordinatorWritingForReplacing 
        error:&fileCoordinatorError 
        byAccessor:^(NSURL *newReadingURL, NSURL *newWritingURL) {
        [fileManager removeItemAtPath:newWritingURL.path error:NULL];
        [fileManager copyItemAtPath:newReadingURL.path 
            toPath:newWritingURL.path error:&fileManagerError];
    }];

如果你不想自己编程,我会分开一个可能有帮助的class(iCloudAccess)。