2012-05-02 43 views
3

我找不到明显的方式来检测我正在监视的文档的删除(我缓存了我的应用程序关心的文档列表)。跨设备检测iCloud中文档删除的正确方法?

Device1上: 当我删除的文档,我叫

 [fileCoordinator coordinateWritingItemAtURL:fileURL options:NSFileCoordinatorWritingForDeleting 
      error:&err byAccessor:^(NSURL* writingURL) { 
      [fileManager removeItemAtURL:writingURL error:nil]; 

这工作Device1上的精细,一切都保持同步。 在设备2: 我试图依靠NSMetadataQuery通知:

初始文件列表以细即将来临NSMetadataQueryDidFinishGatheringNotification 文件添加/更改以细通过NSMetadataQueryDidUpdateNotification

当我删除Device1上的一个文件来,我收到一个奇怪的结果:NSMetadataQueryDidUpdateNotification的更新与我列出的所有文档(已删除的文档除外) 我不确定我应该如何检测丢失的文件是否被删除或更新通知是否为此目的

问题1:我应该检查什么?

我想这是作为一个NSFilePresenter为iCloud的URL注册另一条路线:

- (NSURL *)iCloudDocumentsURL 
{ 
    return [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:@"Documents"]; 
} 

我现在就通过NSFilePresenter协议调用时在URL变化的文件,但它的惩罚性缓慢的运行逻辑确定丢失的文档,因为回调是模糊的。 我回来的唯一电话是- (void)presentedItemDidChange; 我期待通过- (void)accommodatePresentedSubitemDeletionAtURL:(NSURL *)url completionHandler:(void (^)(NSError *errorOrNil))completionHandler 得到回调但是这种方法从来没有被调用过。

问题2:任何想法如何得到这个工作?

回答

3

既然你跟踪文件的以前从iCloud的报道,被删除的文件是从当前的iCloud上市不存在,所以你只比较这两个列表来查找其删除。

这就是我在我的“文件管理器”视图控制器中所做的工作,因为我保留了文件条目的NSMutableDictionary,其中包括文件“图标”在我的主视图中位置的键。当我收到有关更新的通知,并且该更新会导致更多或更少的文件时,我会根据这些文件 更改生成图标更改的动画。

+0

这样你就不知道文件何时被移动。如果你不太在意并在文件包中存储元数据,那很好,但如果你在外面引用文件,那么这种方法不会产生好的结果。 – Andy

2

tobinjim是正确的,因为NSMetadataQuery每次都返回整个结果集。我曾预料只会发送更改以节省带宽,但我没有正确地使用RTFM。

一旦我明白了,我遇到了iOS库中的一个bug。这是当我删除一个设备上的文档和iCloud的查询更新碰到我的其他设备正在发生崩溃:我相信我已经找到这个问题的原因

2012-06-25 13:15:12.343 app[19779:707] *** -[NSMutableIndexSet indexGreaterThanOrEqualToIndex:]: message sent to deallocated instance 0xdaae2c0 
    (gdb) bt 
    #0 0x31937870 in ___forwarding___() 
    #1 0x31892650 in __forwarding_prep_0___() 
    #2 0x373cc676 in __NSIndexSetEnumerate() 
    #3 0x373a1ee8 in -[NSIndexSet enumerateIndexesWithOptions:usingBlock:]() 
    #4 0x371c1f08 in -[LBQuery _processUpdates]() 
    #5 0x373571a6 in -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:]() 
    #6 0x3737ffa4 in -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:]() 
    #7 0x371c2274 in -[LBQuery processUpdates]() 
    #8 0x373a88d6 in -[NSMetadataQuery _update]() 

。我正在审阅Luke the Hiesterman发布的新的IOS 6示例代码。我注意到没有像以前的iCloud示例应用程序那样调用NSMetadataQuery disable/enableUpdates。我删除了对这些的所有呼叫。我也改变了我的方法,它处理NSMetadataQueryDidUpdateNotification调用以异步方式运行,但以排队方式运行。

NSMetadataQuery的线程之间似乎存在竞争条件。在一些调用中,查询的结果很好,但是在其他时候,它们已经被释放,结果显示为NSZombie's(感谢gdb比现有的lldb更好)。因此,跨线程查询的启用和禁用会导致LBQuery通过调用已释放的对象来崩溃。

删除NSMetadataQuery的所有启用和禁用似乎加快了我的应用程序,而且iCloud似乎更加稳定。

+0

确实很有趣。你现在是否像NSMetaDataQueryDidFinishGatheringNotification的观察者那样删除自己,以停止查询的方式停止中断? – tobinjim

+0

我没有。我的回调方法触发了处理异步,所以它不会减慢主线程。我不得不围绕变量添加一些@synchronized块,这些变量可能会被多个异步线程改变。现在稳定和快速,没有崩溃 –