NSMetadataQuery 未完成收集(无通知)

发布于 2024-12-18 17:11:22 字数 2223 浏览 4 评论 0原文

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

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

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

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

I'm making a backup managrer for my App (via iCloud). I did some tests and the basics worked. But few days later it stopped. I'm using NSMetadataQuery for searching if backup file exists. My backup files are named e.g. Backup29112011154133.xml where numbers represent date of the backup (formatted as ddMMyyyyHHmmss). I check for it in -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];
    }
}

The problem is that - (void)queryDidFinishGathering:(NSNotification *)notif is never executed. I put breakpints and NSLogs ion there but nothing happend.

I also tried to check for other notifications e.g. 'query did start gathering' and 'query process'. Only 'query did start' notification is posted.

I also have AppID with iCloud registered and entitlements file attached.

Can you help me out what's going on? Maybe I missed something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

咿呀咿呀哟 2024-12-25 17:11:22

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

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

First of all NSMetadataQuery doesn't works if startQuery was called not from the MaintThread.
There is possibility that predicate fails for every path also.
Following code works for me.

NSURL *mobileDocumentsDirectoryURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
...
query.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%%K like \"%@*\"", [mobileDocumentsDirectoryURL path]], NSMetadataItemPathKey];
[query startQuery];
南薇 2024-12-25 17:11:22

通过为 NSMetadataQuery 创建 ivar 进行修复。

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

FIXED by creating ivar for NSMetadataQuery.

I don't know why the application can't read data without NSMetadataquery ivar.

冰火雁神 2024-12-25 17:11:22

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

Unfortunately there have been many problems with iCloud and using NSMetaDataQuery. To be honest with you the best source as of now for all your iCloud related questions is the Apple Developer Forums. Today Apple released iOS 5.1 beta, and the release notes STILL say that NSMetaDataQuery isn't functioning properly. It's extremely frustrating that iCloud still isn't working properly, but sadly there's nothing we can do.

浮生未歇 2024-12-25 17:11:22

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

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

例如,

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

This problem still persists. I have been able to trace it to the following divergence:

  • If you limit your search predicate on the query to the name key,

for example

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

then it will work as expected (posting all four query lifecycle notifications).

  • If, however, you try either a compound predicate or try to work with the path,

as in

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

OR

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

Then only the initial notification will be posted.

I have tried literally hundreds of combinations of these configurable variables in multiple test and intended-for-production apps over the last year and have yet to find a counterexample to this hypothesis.

Unfortunately, NSMetadataQuery just doesn't work for ubiquitous stores (as of 10.8).

My workaround is to get the raw results from the query and work mostly on a bound NSArrayController which can have its results filtered. This will mean refactoring away from query.results for most existing code and there is a performance hit (presumably) but it is the only way I have found. I would love an alternative.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文