NSMetadataQuery не находит пакеты папок NSFileWrapper, только файлы (но они есть)
У меня странная проблема, которую я не могу решить самостоятельно. Любая помощь или мысль приветствуется.
Эта проблема:
- NSMetadataQuery находит нормальные файлы (например, test.txt), но без пакета обертки файлов (myWrapperDocument.pro)
- Тем не менее, NSFileManager находит все файлы в моем контейнере повсеместности - так что файлы есть, но NSMetadataQuery не находит их!
Факты:
- Приложение на основе UIDocument с использованием NSFileWrappers
- Shared Ubiquity Container (для iOS и настольных приложений)
- Отлично работает на Mac OS
- Прекрасно работает на моем iPad Mini и iPhone 4S и iPhone 3GS (под управлением iOS6 и iOS5)
- Не работает ни на моем iPad1, ни на большинстве устройств моего бета-тестера (iPad 1,2 и 3 под iOS5 или 6)
Что я сделал до сих пор:
- Изучал пример WWDC12 UIDocument & iCloud (CloudNotes.xcodeproj)
- Учился часами на форуме разработчиков Apple и здесь, к сожалению, безуспешно
- Протестировал много разных предикатов, проверил права и настройки документа (чтобы система знала, что это не папка, а пакет документов)
- Очистка и сброс контейнера Ubiquity
Соответствующий код:
Права должны быть правильными; Настройка документа Info.plist (я думаю, что тип документа был зарегистрирован правильно)
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>pro</string>
</array>
<key>CFBundleTypeName</key>
<string>Prowriting Sketch</string>
<key>LSItemContentTypes</key>
<array>
<string>de.ac.prowriting.sketch</string>
</array>
<key>LSTypeIsPackage</key>
<true/>
</dict>
…
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>pro</string>
</array>
<key>LSTypeIsPackage</key>
<true/>
<key>UTTypeConformsTo</key>
<array>
<string>com.apple.package</string>
</array>
<key>UTTypeDescription</key>
<string>Prowriting Sketch</string>
<key>UTTypeIdentifier</key>
<string>de.ac.prowriting.sketch</string>
</dict>
Контейнер ubiquity и URL документов iCloud все в порядке, вот как я настроил запрос:
- (void)startMetadataQuery {
// ...
[self.query setSearchScopes:@[NSMetadataQueryUbiquitousDocumentsScope]];
// search for all .pro documents, also tried other predicates, see below
NSString *predicate = [NSString stringWithFormat:@"%K like '*'"];
[self.query setPredicate:[NSPredicate predicateWithFormat:predicate, NSMetadataItemFSNameKey]];
// register observer (...)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishMetadataQuery:) name:NSMetadataQueryDidFinishGatheringNotification object:nil];
[self.query startQuery];
}
- (void)didFinishMetadataQuery:(NSNotification*)notification {
[self.query disableUpdates];
NSLog(@"+++ found %i results: \n%@", self.query.resultCount, self.query.results);
NSLog(@"+++ Results in iCloud folder: %i", [self.fileManager contentsOfDirectoryAtPath:self.iCloudDocumentsFolder.path error:nil].count);
}
Странно то, что запрос возвращается только с одним файлом "test.txt", но остальные остаются незамеченными. Но, как видно из журнала, в контейнере находится 84 .pro-файла (все они называются "thing.pro"), но запрос находит только один"test.txt".
К сожалению, доступ к этим файлам с помощью NSFileManager не возможен, так как у меня нет прав на их чтение. Я не думаю, что мой контейнер поврежден, поскольку эта проблема также возникает на новых установках устройств моего бета-тестера?
2013-02-18 +++ found 1 results: ("<NSMetadataItem: 0x3ac390> /private/var/mobile/Library/Mobile Documents/ABCD123456~de~ac~prowriting/Documents/test.txt")
2013-02-18 +++ Results in iCloud folder: 84
Я думаю, что это предикат, но:
@"%K like '*.pro*'" // returns nothing
@"%%K like '*.*'" // returns only the test.txt file
@"%%K like '*'" // returns only the test.txt file
@"%K LIKE *" // returns only the test.txt file
@"NSMetadataItemFSNameKey == '*'" // returns only the test.txt file
Я действительно не знаю, что делать дальше. Самое странное, что он работает на некоторых устройствах, но не работает на других устройствах.
Я был бы очень благодарен за любую подсказку по этому вопросу. Большое спасибо!
2 ответа
Как ни странно, мне пришлось удалить параметр LSItemContentTypes из файла info.plist:
<key>LSItemContentTypes</key>
<array>
<string>de.ac.prowriting.sketch</string>
</array>
этот параметр был причиной того, что мой экспортированный пользовательский тип файла UTI filewrapper не был правильно распознан как файл, а интерпретирован как папка. NSMetadataQuery не запрашивает папки, поэтому не нашел ни одного из моих файлов.
К сожалению, у меня также есть приложение для Mac, и мой пользовательский тип файла был правильно зарегистрирован на рабочем столе, что повлияло на папку Mobile Documents iCloud; так что это было причиной, почему это работало на большинстве моих устройств, но ни на одном из моих тестеров.
Вместо поиска по предикату имени файла используйте формат предиката дерева типа UTI.
Я использовал следующее, чтобы вернуть все файлы, папки, пакеты и пакеты по указанному URL-адресу файла:
NSMetadataQuery *query = [NSMetadataQuery new];
[query setSearchScopes:@[url]];
NSPredicate *filePredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypeData];
NSPredicate *bundlePredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypeBundle];
NSPredicate *packagePredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypePackage];
NSPredicate *folderPredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypeFolder];
NSPredicate *searchPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[filePredicate, bundlePredicate, packagePredicate, folderPredicate]];
[query setPredicate:searchPredicate];