NSMetadataQuery 未完成收集(无通知)



我正在为我的应用程序(通过iCloud)制作备份管理器。我做了一些测试,基本功能正常。但几天后,它停止了。我使用 NSMetadataQuery 搜索备份文件是否存在。我的备份文件被命名为例如 Backup29112011154133.xml ,其中数字表示备份日期(格式为 ddMMyyyyHHmmss )。我在-viewDidAppear中检查:

- (void)viewDidAppear:(BOOL)animated {
    [self checkForRemoteFile];
}
- (void)checkForRemoteFile {
    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (ubiq) {
        NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
        [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K like 'Backup*'",NSMetadataItemFSNameKey];
        [query setPredicate:pred];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
        [query startQuery];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"iCloud is unavailable at the moment" message:nil delegate:self cancelButtonTitle:@"Close" otherButtonTitles:nil];
        [alert setTag:TAG_ALERT_NOICLOUD];
        [alert show];
    }
}
- (void)queryDidFinishGathering:(NSNotification *)notif {
    NSMetadataQuery *query = [notif object];
    [query disableUpdates];
    [query stopQuery];
    [self loadRemoteFile:query];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
}
- (void)loadRemoteFile:(NSMetadataQuery *)query {
    if ([query resultCount] == 1) {
        canRestore = YES;
        NSMetadataItem *item = [query resultAtIndex:0];
        // parse the backup file
        [self.tableView reloadData];
    } else {
        canRestore = NO;
        modifDate = @"never";
        backupInfoLoaded = YES;
        [self.tableView reloadData];
    }
}

问题是- (void)queryDidFinishGathering:(NSNotification *)notif永远不会被执行。我在那里放了断点和NSLogs,但是什么也没发生。

我还试着检查其他通知,例如:'query did start gathering'和'query process'。只有'query did start'通知被发送。

我也有AppID与iCloud注册和权利文件附件。

你能告诉我发生了什么事吗?也许我错过了什么?

首先NSMetadataQuery不工作,如果startQuery不是从MaintThread调用。也有可能每个路径的谓词都失败。下面的代码为我工作。

NSURL *mobileDocumentsDirectoryURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
...
query.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%%K like "%@*"", [mobileDocumentsDirectoryURL path]], NSMetadataItemPathKey];
[query startQuery];

修复为NSMetadataQuery创建ivar的问题。

我不知道为什么没有nsmetadatacqueryivar应用程序不能读取数据

不幸的是,iCloud和使用NSMetaDataQuery有很多问题。老实说,到目前为止,所有与iCloud相关的问题最好的来源是苹果开发者论坛。今天苹果发布了iOS 5.1测试版,发行说明STILL说NSMetaDataQuery不能正常工作。非常令人沮丧的是,iCloud仍然不能正常工作,但遗憾的是,我们无能为力。

这个问题仍然存在。我已经能够将其追溯到以下分歧:

  • 如果您将查询上的搜索谓词限制为name键,
例如

[NSPredicate predicateWithFormat:@"%K like[cd] %@", NSMetadataItemFSNameKey, @"*"]

那么它将按预期工作(发布所有四个查询生命周期通知)。

  • 但是,如果您尝试使用复合谓词或尝试使用路径,

[NSPredicate predicateWithFormat:@"%K BEGINSWITH %@", NSMetadataItemPathKey, [self cloudDocumentsURL].path]

[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:namePred, pathPred, nil]];

则只发布初始通知。

在过去的一年里,我在多个测试和用于生产的应用程序中尝试了数百种这些可配置变量的组合,但还没有找到一个反例来支持这一假设。

不幸的是,NSMetadataQuery不能用于无处不在的商店(截至10.8)。

我的解决方法是从查询中获得原始结果,并主要在一个可以过滤其结果的绑定NSArrayController上工作。这将意味着重构远离查询。结果对大多数现有的代码,有一个性能打击(大概),但这是我发现的唯一的方法。

最新更新