iCloud - 在另一台设备上重命名打开的文档有时会失败

Posted

技术标签:

【中文标题】iCloud - 在另一台设备上重命名打开的文档有时会失败【英文标题】:iCloud - renaming open documents on another device sometimes fails 【发布时间】:2011-12-28 13:25:18 【问题描述】:

问题:我正在设备 A 上处理 iCloud 文档,例如iPod 触摸。然后我更改设备 B 上的文档名称,例如我的 Mac(通过 Finder)。更改会上传到云端,并在设备 A 暂停后听到。

然后:

有时一切都很好 - 我通过更改的 fileURL 属性获取名称更改,并可以相应地更新我的界面 - 文档继续按应有的方式运行 有时,文档的 fileURL 会以如下形式返回:file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95 毫不奇怪,此文件不会保存。

谁能解释发生了什么以及如何解决它?

背景

名称更改由NSMetadataQuery 接收。因此,例如,我可以重命名未打开的文档,并且我的所有 iCloud 功能都可以正常工作。该问题似乎只发生在打开的文档中。

其他 iCloud 功能运行良好,例如我可以在一台设备上更改内容,例如我的 Mac,然后在另一台设备上检测并更新我的界面,例如我的 iPod Touch,打开了相关的 iCloud 文档。

当我为我的 UIDocument 子类添加 presentedItemDidMoveToURL: 的覆盖时,我第一次发现了这一点。覆盖可靠地获取在云中进行的名称更改,例如在另一台设备上重命名文档。然后 sometimes newURL 是重命名文档的最终预期 URL,即我可以从中提取新名称使用“lastPathComponent”、更新我的界面等的合理的东西。在其他情况下,newURL 是某些最后一个路径组件以“purg-”开头的其他目录,例如purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95。

- (void) presentedItemDidMoveToURL:(NSURL *) newURL;
   
    [super presentedItemDidMoveToURL: newURL];

    if ([(id)[self delegate] respondsToSelector:@selector(documentNameChanged:)])
    
        [[self delegate] documentNameChanged: self];
    

presentedItemDidMoveToURL: 方法似乎不是问题的根本原因。例如,如果我根本不重写该方法,而是定期检查正在查看打开文档的 viewController,那么在重命名 fileURL 之后 sometimes 将返回新名称并且 有时它会返回“purg-.....”。所以问题似乎与如何处理重命名有关。

更新

正如 al_lea 指出的,这里的问题与 accommodatePresentedItemDeletionWithCompletionHandler: 有关。扩展 al_lea 的答案,我将下面的代码添加到我的 UIDocument 子类中。这解决了这个问题。

    - (void) accommodatePresentedItemDeletionWithCompletionHandler: (void (^) (NSError *errorOrNil)) completionHandler
        
        PresentedDocument* presentedDocument = [self retain];
        [presentedDocument closeWithCompletionHandler: ^(BOOL success)         
            NSError* error = nil;
            if (!success)
            
                NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
                    @"Could not close document that is being deleted on another device",
                    NSLocalizedDescriptionKey, nil];
                    error = [NSError errorWithDomain: @"some_suitable_domain"
                                                code: 101
                                           userInfo: userInfo];
            

        completionHandler(error);  // run the passed in completion handler (required)

        dispatch_async(dispatch_get_main_queue(), ^
        
           [[NSNotificationCenter defaultCenter] postNotificationName: NOTIFY_presentedDocumentDeletedOnAnotherDevice
                                                               object: presentedDocument
                                                             userInfo: nil];

           [presentedDocument tidyUpAfterDelete];  // app specific tidy up
           [presentedDocument release];
       );
    ];

有了这段代码,就不会出现虚假和令人困惑的presentedItemDidMoveToURL: 调用,此外,相关对象可以侦听其他设备上的删除通知。

【问题讨论】:

我尝试仅使用 DocumentState 使 iCloud 工作大约一个月——这是我缺少的部分。在添加此代码之前,项目有时会在删除后返回,或者我会得到不断变化的文档状态的连续流 【参考方案1】:

当在本地打开 UIDocument 并从远程设备中删除时,会出现这种类型的 URL:

file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-

您需要先关闭文档,然后才能将其删除 - 在 NSFilePresenter 的 accommodatePresentedItemDeletionWithCompletionHandler: 中检测到这一点

【讨论】:

以上是关于iCloud - 在另一台设备上重命名打开的文档有时会失败的主要内容,如果未能解决你的问题,请参考以下文章

iOS iCloud 文档更改通知

无法在设备之间进行 iCloud 同步

强制 iOS 将文件上传到 iCloud

使用CMD打开word文档到另一台电脑,它只停留在任务管理器的进程选项卡中,不显示在另一台电脑的屏幕上

仅限在线的 iCloud 密钥存储

如何通知另一台设备 CloudKit 记录已更新?