6

Apple Docs NSMetadataQuery で説明されているように、iCloud ファイルを検索するために使用しました。私はファイルを 1 つしか持っておらず、その名前を知っています。私の問題は、このファイルが存在しない場合があり (まだダウンロードされていないためだと思います)、NSMetadataQuery がそれを見つけることができないことです。

ダウンロードを強制しようとしたNSFileManager startDownloadingUbiquitousItemAtURL:error:ことがありますが、エラーが返されます。(編集を読む)

私の解決策は、最初にファイルを作成し、それが存在すると推測し、UIDocument で開くことです。しかし、存在しないか、ユーザーが初めてアプリを開いた可能性があります。私はこれらのことについて確信が持てません。私の最初の質問は、UIDocument がファイルを開く場合、それはファイルがどこかに見つかったことを意味します。ファイルが存在しない場合、どのようにファイルを使用できますか?

次に、2 番目の質問: 複数のファイルまたは名前が不明なファイルを管理する必要があるアプリの場合。NSMetadataQuery が機能しない場合、どうすればそれらを見つけることができますか?

EDIT: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'
    }
4

3 に答える 3

7

iCloudファイルの次のロードルーチンをお勧めします。これには 4 つのステップが含まれます。

  1. まず、iCloud にアクセスできるかどうかをテストします
  2. 次に、ファイルを探します(指定したような特定のファイルを探すか、* .txtなどの特定の拡張子を持つすべてのファイルを探すか、探しているファイル拡張子が本当にわからない場合は、次のようなものNSPredicate *pred = [NSPredicate predicateWithFormat:@"NOT %K.pathExtension = '.'", NSMetadataItemFSNameKey];がすべてのファイルを返します拡張子は jpg、txt、dat など)
  3. 次に、クエリが完了したかどうかを確認し、
  4. 最後にファイルのロードを試みます。ファイルが存在しない場合は、作成します。存在する場合は、ロードします。

これらの 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;
}
于 2011-10-31T07:44:22.923 に答える
1

edo42、問題は解決しましたか? AT&T に戻るために新しい 4S を購入し、最初の 4S をバックアップしてから、新しい 4S でバックアップから復元したところ、これが発生していました。

  1. [iCloudFileURL getResource:&fileState forKey:NSURLIsUbiquitousItemKey error:&error] を実行すると、同じエラーが発生します。

エラー Domain=NSPOSIXErrorDomain Code=2 「操作を完了できませんでした。そのようなファイルまたはディレクトリはありません」 UserInfo=0x448500 {NSDescription=Path '/private/var/mobile/Library/Mobile Documents/~UbiquitousDir の実際のパスを取得できません~/Documents/MyDocument.ext'

(私の iPad 2 では正常に動作します)

  1. 次に、NSMetadataQuery を実行しますが、結果が返されません。(iCloud でドキュメントを表示するには、iPad 2 で問題なく動作します)。

  2. ユビキタスファイルが存在することを確認しましたが、エラーが示唆するように存在しません。

  3. [fileMgr evictUbiquitousItemAtURL:ubiquitousDocumentsDir &error] を使用してみましたが、成功します。しかし、NSMetadataQuery を試してみると、まだ結果が返されません。

これが、両方のケースで何が間違っているかを理解するのに役立つことを願っています.

更新:バックアップから復元したこのデバイスのiCloudには実際の問題があります:

  1. iPhone デバイスからアプリを削除しました。
  2. ストレージの管理からアプリのバックアップ ファイルを削除しました。
  3. アプリのファイルを iCloud (ドキュメントとデータ) のマネージド ストレージから削除しました。
  4. iCloud ファイルはもうありません。iPad 2 を見てみると、消えていました。
  5. iPad 2 でアプリを起動したところ、新しい iCloud ドキュメントが正常に保存されました。
  6. 新しい iCloud ファイルが iPhone に表示されます。
  7. デバイスでアプリをビルドして実行しましたが、NSMetadaQuery クエリでファイルをダウンロードできません。
于 2011-11-30T14:26:25.887 に答える
0

同様の問題がありました.metadataQueryDidUpdateとmetadataQueryDidFinishGatheringが起動しますが、NSMetadataQueryの結果は空になります。プロビジョニング プロファイルの問題がありましたが、デバイスでテストしようとするまで、Xcode からは通知されず、バンドル ID が無効であると言って失敗しました (そうではありませんでした)。

私にとってそれを修正したのは、設定に移動し、プロビジョニングプロファイルの[すべてダウンロード]ボタンをクリックしてから、Xcodeでクリーンを実行することでした. 再構築して実行すると、すべてのファイルが表示されました。開発者ポータルにチェックインして、プロファイルが無効としてマークされていないことを確認してください。私の場合はそうではなかったので、これをトリガーする必要はありませんが、発生する可能性があります。

正確には科学的ではありませんが、これは私にとってはうまくいきました。

于 2016-07-11T11:05:34.303 に答える