NSMetadataQuery не заканчивает сбор (нет уведомления)
Я создаю менеджер резервного копирования для своего приложения (через 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
никогда не выполняется. Я поставил туда брейкпинты и Нслоги, но ничего не произошло.
Я тоже пытался проверьте наличие других уведомлений, например "запрос действительно начал собираться" и "процесс запроса". Публикуется только уведомление "запрос запущен".
У меня также есть AppID с зарегистрированным iCloud и прикрепленным файлом прав.
Не могли бы вы помочь мне разобраться, что происходит? Может быть, я что-то пропустил?4 ответа:
Во-первых, NSMetadataQuery не работает, если startQuery был вызван не из MaintThread. Существует вероятность, что предикат не работает и для каждого пути. Следующий код работает для меня.
NSURL *mobileDocumentsDirectoryURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; ... query.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%%K like \"%@*\"", [mobileDocumentsDirectoryURL path]], NSMetadataItemPathKey]; [query startQuery];
Исправлено путем создания
ivar
дляNSMetadataQuery
.Я не знаю, почему приложение не может читать данные без NSMetadataquery ivar.
К сожалению, было много проблем с iCloud и использованием
NSMetaDataQuery
. Чтобы быть честным с вами, лучший источник на данный момент для всех ваших вопросов, связанных с iCloud, - это форумы разработчиков Apple. Сегодня Apple выпустила бета-версию iOS 5.1, и в примечаниях к выпуску по-прежнему говорится, что NSMetaDataQuery не функционирует должным образом. Крайне неприятно, что iCloud все еще не работает должным образом, но, к сожалению, мы ничего не можем сделать.
Эта проблема все еще сохраняется. Я смог проследить его до следующего расхождения:
- Если вы ограничиваете предикат поиска в запросе ключом name,
Например
[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, который может фильтровать свои результаты. Этот будет означать рефакторинг от запроса.результаты для большинства существующих кодов и есть хит производительности (предположительно), но это единственный способ, который я нашел. Мне бы очень хотелось иметь альтернативу.