【问题标题】:NSMetadataQuery doesn't finish gathering (no notification)NSMetadataQuery 没有完成收集(没有通知)
【发布时间】:2012-01-08 21:50:28
【问题描述】:

我正在为我的应用程序创建备份管理器(通过 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 但什么也没发生。

我还尝试检查其他通知,例如“查询确实开始收集”和“查询过程”。仅发布“查询已开始”通知。

我还有注册了 iCloud 并附加了权利文件的 AppID。

你能帮我看看发生了什么事吗?也许我错过了什么?

【问题讨论】:

    标签: iphone ios5 icloud nsmetadataquery


    【解决方案1】:

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

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

    例如

    [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 上工作,它可以过滤其结果。这将意味着从 query.results 重构大多数现有代码,并且会影响性​​能(大概),但这是我找到的唯一方法。我想要一个替代方案。

    【讨论】:

      【解决方案2】:

      已通过为 NSMetadataQuery 创建 ivar 来修复。

      我不知道为什么应用程序在没有 NSMetadataquery ivar 的情况下无法读取数据。

      【讨论】:

      • 如果你使用 ARC,你的 NSMetaDataQuery 会在作用域结束后被释放。你需要一个 iVar 来保留它
      • 好的,现在我明白了。谢谢! ;)
      【解决方案3】:

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

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

      【讨论】:

      • 是的,但它工作并突然停止,所以我认为这不是问题..
      • FalconSer,我已尝试使用上述谓词进行查询,但出现异常。它说无法解析正则表达式等。它应该是@"%K BEGINSWITH %@", NSMetadataItemPathKey, [mobileDocumentsDirectoryURL path]]](注意只有百分之一,%@ 周围没有引号,并且参数是倒序的。如果需要使用BEGINGWITH[cd] 而不是BEGINGWITH
      • 谢谢!我不是从主线程调用的,你的回答对我很有帮助。
      【解决方案4】:

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

      【讨论】:

      • 有没有其他方法可以在不使用 NSMetadataQuery 的情况下处理 iCloud 上的文件?
      • 自从 iCloud Documents API 发布以来已经经历了许多“轮回”,我的知识可能有点过时(我一直在专门使用 Core Data,UIManagedDocument),但是当我使用要使用 NSMetaDataQuery 加载数据,我必须加载每个文件。没有像使用 iCloud 那样令人沮丧的唯一方法是使用 Apple 的文档代码(NSMetaDataQuery)。
      猜你喜欢
      • 2014-06-21
      • 2019-03-20
      • 1970-01-01
      • 2017-09-18
      • 1970-01-01
      • 2018-02-12
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      相关资源
      最近更新 更多