NSMetadataQuery не заканчивает сбор (без уведомления)

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

Решение

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

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

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

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

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

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

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

например

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

Другие вопросы по тегам