3

我找不到一种明显的方法来检测我正在监视的文档的删除(我缓存了我的应用程序关心的文档列表)。

在 Device1 上:当我删除一个文档时,我调用

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

这在 Device1 上运行良好,一切都保持同步。在 Device2 上:我试图依靠NSMetadataQuery通知:

初始文件列表在NSMetadataQueryDidFinishGatheringNotification 文档添加/更改中正常通过NSMetadataQueryDidUpdateNotification

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

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

我尝试了另一条路线,即注册为NSFilePresenteriCloud URL:

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

现在,NSFilePresenter当该 URL 中的文件发生更改时,我会通过协议进行调用,但是由于回调是模糊的,因此运行逻辑以确定丢失的文档是非常缓慢的。我得到的唯一电话是我希望通过 但从未调用过此方法- (void)presentedItemDidChange; 来获得回调。- (void)accommodatePresentedSubitemDeletionAtURL:(NSURL *)url completionHandler:(void (^)(NSError *errorOrNil))completionHandler

问题2:知道如何让它工作吗?

4

3 回答 3

3

由于您正在跟踪以前从 iCloud 报告的文件,因此当前iCloud 列表中不存在已删除的文件,因此您只需比较两个列表即可找到已删除的文件。

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

于 2012-06-15T15:33:20.170 回答
2

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

一旦我弄清楚了,我就在 iOS 库中遇到了一个错误。这是当我在一台设备上删除文档并且 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 的(感谢 gdb,它比当前的 lldb 好得多)。所以跨线程启用和禁用查询会导致 LBQuery 通过调用已释放的对象而崩溃。

取消所有对 NSMetadataQuery 的启用和禁用似乎也加快了我的应用程序的速度,而且 iCloud 似乎更加稳定。

于 2012-06-25T20:58:09.430 回答
1

由于 iOS 8NSMetadataQuery扩展NSMetadataQueryDidUpdateNotification了 userInfo NSMetadataQueryUpdateRemovedItemsKey,您可以使用它来检测哪些文件被删除。

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSMetadataQuery_Class/#//apple_ref/doc/constant_group/Keys_for_Use_with_a_Notification_Info_Dictionary

于 2015-12-27T21:45:53.020 回答