NSMetadataQuery doesn't finish gathering (no notification)

泪湿孤枕 提交于 2019-12-10 06:36:25

问题


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?


回答1:


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];



回答2:


FIXED by creating ivar for NSMetadataQuery.

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




回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/8312749/nsmetadataquery-doesnt-finish-gathering-no-notification

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!