问题:我正在处理设备 A 上的 iCloud 文档,例如 iPod Touch。然后我更改设备 B 上文档的名称,例如我的 Mac(通过 Finder)。更改会上传到云端,并在设备 A 暂停后听到它。
进而:
- 有时一切都很好-我通过更改的
fileURL
属性获取名称的更改,并可以相应地更新我的界面-文档继续按应有的方式运行 - 有时,文档的 fileURL 会以如下形式返回:
file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95
毫不奇怪,此文件不会保存。
谁能解释发生了什么以及如何解决它?
背景
名称更改由 by 很好地接受
NSMetadataQuery
。因此,例如,我可以重命名未打开的文档,并且我的所有 iCloud 功能都可以正常工作。该问题似乎只发生在打开的文档中。其他 iCloud 功能运行良好,例如,我可以更改一台设备(例如我的 Mac)上的内容,然后检测并更新我在另一台设备(例如我的 iPod Touch)上打开相关 iCloud 文档的界面。
presentedItemDidMoveToURL:
当我为我的 UIDocument 子类添加覆盖时,我第一次发现了这一点。覆盖可靠地拾取在云中进行的名称更改,例如在另一个设备上重命名文档。然后有时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
会返回新名称,有时会返回 `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: 调用,此外,相关对象可以监听其他设备上的删除通知。