3

次のように、iCloud をサポートする新しい UIManagedDocument を作成しています。

  1. ローカル サンドボックス URL を割り当てて初期化する
  2. iCloud をサポートする永続ストア オプションを設定します: ubiquitousContentNameKey および ubiquitousContentURL。私が一意に生成している名前で、URL は私の ubiquityContainer / CoreData を指しています。
  3. UIManagedDocument の saveToURL メソッドを使用してサンドボックスにローカルに保存します。
  4. 完了ハンドラーでは、FileManager の setUbiquitous メソッドで iCloud に移動します。

これまでのところ、このダンスは機能します。(まあ、ちょっと)。setUbiquitous を呼び出した後、成功しなかったというエラーが表示されますが、ドキュメントはクラウドに移動します。完了すると、クラウドに新しいドキュメントが作成されます。他の人のコードで再現できたので、これはバグのようです。

このドキュメントは、クラウド内のすべてのドキュメントを一覧表示する「Documents View Controller」で実際に生成しています。したがって、この新しいドキュメントの最終的な完了ハンドラが完了すると、NSMetadataQuery のおかげでテーブル ビューに表示されます。これまでのところ、かなり標準的な使い方だと思います。

ドキュメントを編集するには、ユーザーはタップして「Single View Document View Controller」に移動します。

このView Controllerでは、ユーザーが編集できるように、選択したドキュメントを「再度開く」必要があります。

したがって、一連の手順をもう一度実行します。

  1. fileURL を使用して UIManagedDocument を割り当て/初期化します。今回は、URL はクラウドからのものです。
  2. 上記の手順 2 と同じ設定で、永続ストア オプションを設定します。

ここで、ディスクからドキュメントを開くステップ 3 を試みましたが、失敗しました。ドキュメントは「Closed | SavingError」の状態にあり、開こうとすると失敗します。

ドキュメントの作成はOKで、クラウドへの移動はOKなのに、その後すぐに開くことができない理由を知っている人はいますか? (実際には、アプリのその起動内での試み - 以下を参照してください)。具体的には、UIManagedDocument インスタンスを作成するが、閉じた、開くことができない状態にするのは何ですか?

興味深いことに、アプリを終了して再度起動すると、ドキュメントをタップして再読み込みし、編集することができます。

そして、非常にまれに、作成してから開き、非常に簡単に編集することができます。たとえば、1 つの管理対象オブジェクトを挿入すると、このクローズ | エラー状態を保存しています。

エラー情報:

私は UIManagedDocument をサブクラス化し、 -handleError: メソッドをオーバーライドして、より多くの情報を取得しようとしました。これが私が得たものです (私が入れた他のデバッグ ログと共に):

2012-10-05 14:57:06.000 Foundations[23687:907] 単一ドキュメント ビュー コントローラー ビューが読み込まれました。ドキュメント: fileURL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ documentState: [Closed]

2012-10-05 14:57:06.052 MyApp[23687:907] ドキュメントの状態が変更されました。現在の状態: 5 fileURL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ documentState: [Closed | 保存エラー]

2012-10-05 14:57:06.057 Foundations[23687:5303] UIManagedDocument エラー: ストア名: 新しいドキュメント 34 は既に使用されています。ストア URL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore 使用中ストア URL: file:/ /localhost/var/mobile/Applications/D423F5FF-4B8E-4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore

2012-10-05 14:57:06.059 MyApp[23687:5303] { NSLocalizedDescription = "ストア名: 新しいドキュメント 34 は既に使用されています。\n\tストア URL: file://localhost/private/var/mobile/ Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n\t使用中のストア URL: file://localhost/var/mobile/Applications/D423F5FF-4B8E -4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n"; NSPersistentStoreUbiquitousContentNameKey = "新しいドキュメント 34"; }

エラーは、その後のオープン時に既に存在するストアを作成していると思われるようです。2 回目のオープン時に永続ストアでこれらの iCloud オプションを設定することになっていますか? 私はそのアプローチを試みましたが、うまくいきませんでした。

UIManagedDocument に関するスタンフォード大学の講義を研究しましたが、何が間違っているのかわかりません。

ドキュメントを作成してクラウドに移行する方法は次のとおりです。

- (void) testCreatingICloudDocWithName:(NSString*)name
{

    NSURL* cloudURL = [self.docManager.iCloudURL URLByAppendingPathComponent:name isDirectory:YES];

    NSURL* fileURL = [self.docManager.localURL URLByAppendingPathComponent:name];


    self.aWriting = [[FNFoundationDocument alloc] initWithFileURL:fileURL];


    [self setPersistentStoreOptionsInDocument:self.aWriting];

    [self.aWriting saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
        if (success == YES) {

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                //create file coordinator
                //move document to icloud

                NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
                NSError* coorError = nil;
                [fileCoordinator coordinateWritingItemAtURL:cloudURL options:NSFileCoordinatorWritingForReplacing error:&coorError byAccessor:^(NSURL *newURL) {

                    if (coorError) {
                        NSLog(@"Coordinating writer error: %@", coorError);
                    }

                    NSFileManager* fm = [NSFileManager defaultManager];
                    NSError* error = nil;
                    NSLog(@"Before set ubiq");
                    [fm setUbiquitous:YES itemAtURL:fileURL destinationURL:newURL error:&error];
                    if (!error) {
                        NSLog(@"Set ubiquitous successfully.");
                    }
                    else NSLog(@"Error saving to cloud. Error: %@", error);


                    NSLog(@"State of Doc after error saving to cloud: %@", self.aWriting);
                }];



            });

        }
    }];

}

ここで、persistentStore で iCloud のオプションを設定します。

- (void)setPersistentStoreOptionsInDocument:(FNDocument *)theDocument
{
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

    [options setObject:[theDocument.fileURL lastPathComponent] forKey:NSPersistentStoreUbiquitousContentNameKey];
    NSURL* coreDataLogDirectory = [self.docManager.coreDataLogsURL URLByAppendingPathComponent:[theDocument.fileURL lastPathComponent]];
    NSLog(@"Core data log dir: %@", coreDataLogDirectory);
    [options setObject:coreDataLogDirectory forKey:NSPersistentStoreUbiquitousContentURLKey];

    theDocument.persistentStoreOptions = options;
}

そして、ここで私はそれを再開しようとしています:

- (void) prepareDocForUse
{

    NSURL* fileURL = self.singleDocument.fileURL;

    if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
        NSLog(@"File doesn't exist");
            }
    else if (self.singleDocument.documentState == UIDocumentStateClosed) {
        // exists on disk, but we need to open it
        [self.singleDocument openWithCompletionHandler:^(BOOL success) {
            if (!success) {
                NSError* error;
                [self.singleDocument handleError:error userInteractionPermitted:NO];
            }
            [self setupFetchedResultsController];
        }];
    } else if (self.singleDocument.documentState == UIDocumentStateNormal) {
        // already open and ready to use
        [self setupFetchedResultsController];
    }

}
4

2 に答える 2

0

私は iOS7 をターゲットにしています。Apple のドキュメントで提案されているように、CoreData と iCloud をより適切に統合することを目標に、単一の UIManagedDocument をアプリ DB として使用しています。私は同じ問題を抱えていました。次のコードで解決しました。

私が書いたので、UIManagedDocument の遅延インスタンス化内に PSC オプション設定を移動しました。

私の元のコードは、成功した標準関数でコールバックを使用してドキュメントを作成し、閉じてから再度開きました。エリカ・サドゥンの本で見つけました。すべて問題ないように見えましたが、「保存エラー」状態だったため、作成して閉じたばかりのドキュメントを再度開くことができませんでした。再開するまではすべてが完璧だったので、自分が何を間違っていたのか理解できませんでした。

次のコードは、私の iPhone5 と iPad3 で完全に動作します。

ニコラ

-(void) fetchDataWithBlock: (void (^) (void)) fetchingDataBlock
{

    //If the CoreData local file exists then open it and perform the query
    if([[NSFileManager defaultManager] fileExistsAtPath:[self.managedDocument.fileURL path]]){
        NSLog(@"The CoreData local file in the application sandbox already exists.");

        if (self.managedDocument.documentState == UIDocumentStateNormal){
            NSLog(@"The CoreData local file it's in Normal state. Fetching data.");
            fetchingDataBlock();
        }else if (self.managedDocument.documentState == UIDocumentStateClosed){
            NSLog(@"The CoreData local file it's in Closed state. I am opening it.");

            [self.managedDocument openWithCompletionHandler:^(BOOL success) {
                if(success){
                    NSLog(@"SUCCESS: The CoreData local file has been opened succesfully. Fetching data.");
                    fetchingDataBlock();
                }else{
                    NSLog(@"ERROR: Can't open the CoreData local file. Can't fetch the data.");
                    NSLog(@"%@", self.managedDocument);
                    return;
                }
            }];
        }else{
            NSLog(@"ERROR: The CoreData local file has an unexpected documentState: %@", self.managedDocument);
        }
    }else{
        NSLog(@"The CoreData local file in the application sandbox did not exist.");
             NSLog(@"Setting the UIManagedDocument PSC options.");
        [self setPersistentStoreOptionsInDocument:self.managedDocument];

        //Create the Core Data local File
        [self.managedDocument saveToURL:self.managedDocument.fileURL
                       forSaveOperation:UIDocumentSaveForCreating
                      completionHandler:^(BOOL success) {

            if(success){

                NSLog(@"SUCCESS: The CoreData local file has been created. Fetching data.");
                fetchingDataBlock();

            }else{
                NSLog(@"ERROR: Can't create the CoreData local file in the application sandbox. Can't fetch the data.");
                NSLog(@"%@", self.managedDocument);
                return;
            }

        }];

    }
}
于 2013-11-19T17:00:58.430 に答える
0

最近、さまざまなバージョンの iOS をテストしていますか? 保存したドキュメントのタイトルを「New Document 34」以外に変更してみてください。同じ問題が発生していて、同じドキュメント URL を使用してアプリのさまざまな SDK コンパイルから保存された競合するドキュメントに関係していると思います。

于 2013-03-02T06:05:48.130 に答える