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