NSMetadataQuery не находит файлы iCloud - PullRequest
6 голосов
/ 31 октября 2011

Я использовал, как описано в Apple Docs NSMetadataQuery, для поиска в моем файле iCloud.У меня есть только один файл, и я знаю его имя.Моя проблема в том, что иногда этот файл не существует (я думаю, потому что он еще не был загружен), и NSMetadataQuery не может его найти.

Когда-либо пытался принудительно загрузить с NSFileManager startDownloadingUbiquitousItemAtURL:error:, и он возвращает мнеошибка.(Прочтите РЕДАКТИРОВАТЬ)

Мое решение состоит в том, что я создал файл в первый раз, а затем, думаю, он существует, и я открываю его с помощью UIDocument.Но он не может существовать или это может быть первый раз, когда пользователь открывает приложение.Я не могу быть уверен в этих вещах.Мой первый вопрос: если UIDocument открывает файл, это означает, что он где-то нашел файл.Как он может использовать файл, если он НЕ СУЩЕСТВУЕТ?

И затем второй вопрос: если я приложение, которое должно управлять несколькими файлами или файлами с неизвестным именем.Как я могу найти их, если NSMetadataQuery не работает.

РЕДАКТИРОВАТЬ: , если startDownloadingUbiquitousItemAtURL должен использоваться, чтобы начать загрузку файла, как я могу узнать, когда файл закончил загрузку (возможно,с уведомлением)?Но, более важная вещь: как я могу скачать файл, если всегда говорится (удалены оригинальные имена)?

   Error Domain=NSPOSIXErrorDomain Code=2 "The operation couldn’t be completed.
    No such file or directory" UserInfo=0x166cb0 {
    NSDescription=Unable to get real path for Path
'/private/var/mobile/Library/Mobile Documents/teamid~com~team~app/Documents/file.extension'
    }

Ответы [ 3 ]

7 голосов
/ 31 октября 2011

Я предлагаю следующую процедуру загрузки для файлов iCloud. Он включает 4 шага:

  1. Во-первых, проверка доступности iCloud
  2. затем найдите ваши файлы (либо найдите определенный файл, который вы указали, либо все файлы с определенным расширением, например * .txt, или, если вы действительно не знаете, какое расширение файла вы ищете, что-то вроде NSPredicate *pred = [NSPredicate predicateWithFormat:@"NOT %K.pathExtension = '.'", NSMetadataItemFSNameKey]; вернет все файлы с расширением, такие как jpg, txt, dat и т. Д.)
  3. затем проверка выполнения запроса и
  4. наконец попытайтесь загрузить файл. Если файл не существует, создайте его. Если он существует, загрузите его.

Вот код, который иллюстрирует эти четыре шага:

    - (void)loadData:(NSMetadataQuery *)query {

    // (4) iCloud: the heart of the load mechanism: if texts was found, open it and put it into _document; if not create it an then put it into _document

    if ([query resultCount] == 1) {
        // found the file in iCloud
        NSMetadataItem *item = [query resultAtIndex:0];
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:url];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc openWithCompletionHandler:^(BOOL success) {
            if (success) {
                NSLog(@"AppDelegate: existing document opened from iCloud");
            } else {
                NSLog(@"AppDelegate: existing document failed to open from iCloud");
            }
        }];
    } else {
        // Nothing in iCloud: create a container for file and give it URL
        NSLog(@"AppDelegate: ocument not found in iCloud.");

        NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
        NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:@"text.txt"];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:ubiquitousPackage];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc saveToURL:[doc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            NSLog(@"AppDelegate: new document save to iCloud");
            [doc openWithCompletionHandler:^(BOOL success) {
                NSLog(@"AppDelegate: new document opened from iCloud");
            }];
        }];
    }
}

- (void)queryDidFinishGathering:(NSNotification *)notification {

    // (3) if Query is finished, this will send the result (i.e. either it found our text.dat or it didn't) to the next function

    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];

    [self loadData:query];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
    _query = nil; // we're done with it
}

-(void)loadDocument {

    // (2) iCloud query: Looks if there exists a file called text.txt in the cloud

    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
    _query = query;
    //SCOPE
    [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
    //PREDICATE
    NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, @"text.txt"];
    [query setPredicate:pred];
    //FINISHED?
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
    [query startQuery];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"AppDelegate: app did finish launching");
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil] autorelease];
    } else {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil] autorelease];
    }

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    // (1) iCloud: init

    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (ubiq) {
        NSLog(@"AppDelegate: iCloud access!");
        [self loadDocument];
    } else {
        NSLog(@"AppDelegate: No iCloud access (either you are using simulator or, if you are on your phone, you should check settings");
    }


    return YES;
}
1 голос
/ 30 ноября 2011

edo42, вы решили проблему? Я купил новый 4S, чтобы вернуться в AT & T, и я сделал резервную копию своего первого 4S, а затем восстановился из резервной копии на новом 4S, и тогда это произошло для меня.

  1. Когда я делаю [iCloudFileURL getResource: & fileState forKey: NSURLIsUbiquitousItemKey error: & error], я получаю ту же ошибку.

Ошибка домена = NSPOSIXErrorDomain Code = 2 "Операция не может быть завершена. Нет такого файла или каталога" UserInfo = 0x448500 {NSDescription = Невозможно получить реальный путь для пути '/ private / var / mobile / Library / Mobile Documents /~UbiquitousDir~/Documents/MyDocument.ext'

(отлично работает на моем iPad 2)

  1. Тогда я бы сделал NSMetadataQuery, но потом он вернулся без результатов. (Работает на моем iPad 2 просто отлично, чтобы увидеть документ на iCloud).

  2. Я проверил, существует ли вездесущий файл, но его там нет, как предполагает ошибка.

  3. Я попытался использовать [fileMgr evictUbiquitousItemAtURL: ubiquitousDocumentsDir & error], и это действительно успешно. Но когда я пытаюсь выполнить NSMetadataQuery, он все равно возвращается без результатов.

Надеюсь, это поможет понять, что не так в обоих случаях.

ОБНОВЛЕНИЕ: Хорошо, существует реальная проблема с iCloud для этого устройства, которое я восстановил из резервной копии:

  1. Я удалил свое приложение с устройства iPhone.
  2. Я удалил файлы резервных копий своего приложения из Manage Storage.
  3. Я даже удалил файл для своего приложения из iCloud (Документы и данные) в разделе Управляемое хранилище.
  4. Файл iCloud больше не существует, и я смотрю на iPad 2, и его больше нет.
  5. Я запустил свое приложение на iPad 2, и он успешно сохранил новый документ iCloud.
  6. Новый файл iCloud отображается на моем iPhone.
  7. Я собираю и запускаю приложение на своем устройстве, но он не может загрузить файл с помощью запроса NSMetadaQuery.
0 голосов
/ 11 июля 2016

У меня была похожая проблема, сработали metadataQueryDidUpdate и metadataQueryDidFinishGathering, но результаты NSMetadataQuery были бы пустыми. Была проблема с профилем обеспечения, о которой Xcode не сообщал мне до тех пор, пока я не попытался протестировать его на своем устройстве, где произошел сбой, сказав, что мой идентификатор пакета был недействительным (это не так).

Что исправило для меня, так это перейти в «Предпочтения» и нажать кнопку «Загрузить все» для профилей инициализации, а затем выполнить «Очистку в Xcode». Перестройте, запустите, и все мои файлы обнаружились. Зайдите на портал разработчиков, чтобы убедиться, что ни один из ваших профилей не помечен как недействительный. Ничего из этого не было, так что запускать его не обязательно, но это может произойти.

Не совсем научный, но у меня это сработало.

...