NSMetadataQuery无法完成收集(无通知)

时间:2011-11-29 14:49:00

标签: iphone ios5 icloud 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永远不会被执行。我把breakpints和NSLogs放在那里,但没有任何事情发生。

我还尝试检查其他通知,例如'查询确实开始收集'和'查询过程'。只发布'query did start'通知。

我也有附加了iCloud注册和权利文件的AppID。

你能帮我解决一下发生的事吗?也许我错过了什么?

4 个答案:

答案 0 :(得分:17)

首先,如果不是从MaintThread调用startQuery,则NSMetadataQuery不起作用。 每个路径都有可能出现谓词失败。 以下代码适用于我。

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

答案 1 :(得分:9)

通过为ivar创建NSMetadataQuery来修复。

我不知道为什么没有NSMetadataquery ivar,应用程序无法读取数据。

答案 2 :(得分:2)

不幸的是,iCloud和使用NSMetaDataQuery存在许多问题。老实说,对于所有与iCloud相关的问题,目前最好的来源是Apple Developer论坛。今天Apple发布了iOS 5.1 beta版,发布说明 STILL 表示NSMetaDataQuery运行不正常。令人非常沮丧的是,iCloud仍然无法正常工作,但遗憾的是我们无能为力。

答案 3 :(得分:0)

此问题仍然存在。我已经能够追踪到以下分歧:

  • 如果您将查询的搜索谓词限制为名称密钥,

例如

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

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

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

,如

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

OR

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

然后只会发布初始通知。

去年,我在多个测试和预期生产应用程序中尝试了数百种这些可配置变量的组合,并且尚未找到这种假设的反例。

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

我的解决方法是从查询中获取原始结果,并主要在绑定的NSArrayController上工作,该结果可以过滤其结果。这意味着从大多数现有代码的query.results重构,并且有一个性能损失(可能),但这是我找到的唯一方法。我希望有另一种选择。