NSMetadataQuery не заканчивает сбор (без уведомления) - PullRequest
5 голосов
/ 29 ноября 2011

Я делаю резервную копию менеджера для моего приложения (через 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, но ничего не произошло.

Я также попытался проверить другие уведомления, например, «запрос начал собираться» и «процесс запроса».Размещено только уведомление «запрос запущен».

У меня также есть AppID с зарегистрированным iCloud и приложенным файлом разрешений.

Можете ли вы мне помочь, что происходит?Может я что то пропустил?

Ответы [ 4 ]

17 голосов
/ 01 декабря 2011

Прежде всего NSMetadataQuery не работает, если startQuery был вызван не из MaintThread. Существует вероятность того, что предикат не работает и для каждого пути. Следующий код работает для меня.

NSURL *mobileDocumentsDirectoryURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
...
query.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%%K like \"%@*\"", [mobileDocumentsDirectoryURL path]], NSMetadataItemPathKey];
[query startQuery];
9 голосов
/ 10 декабря 2011

ИСПРАВЛЕНО созданием ivar для NSMetadataQuery.

Я не знаю, почему приложение не может читать данные без NSMetadataquery ivar.

2 голосов
/ 29 ноября 2011

К сожалению, было много проблем с iCloud и использованием NSMetaDataQuery.Честно говоря, лучшим источником на все ваши вопросы, связанные с iCloud, являются форумы разработчиков Apple.Сегодня Apple выпустила бета-версию iOS 5.1, и в примечаниях к выпуску STILL говорится, что NSMetaDataQuery не работает должным образом.Очень печально, что iCloud по-прежнему не работает должным образом, но, к сожалению, мы ничего не можем сделать.

0 голосов
/ 23 октября 2012

Эта проблема все еще сохраняется. Я смог проследить это до следующего расхождения:

  • Если вы ограничите свой предикат поиска в запросе ключом имени,

например

[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 для большей части существующего кода, и есть снижение производительности (предположительно), но это единственный способ, который я нашел. Я хотел бы альтернативу.

...