1

Core Data を使用し、iCloud と同期するアプリを作成しています。これを行うには、以下に示すように設定した UIManagedDocument があります。

UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:[self iCloudStoreURL]];
        document.persistentStoreOptions = @{NSPersistentStoreUbiquitousContentNameKey: [document.fileURL lastPathComponent], NSPersistentStoreUbiquitousContentURLKey: [self iCloudCoreDataLogFilesURL], NSMigratePersistentStoresAutomaticallyOption: @YES, NSInferMappingModelAutomaticallyOption : @YES};
        self.mydoc = document;
        [document release];

        [document.managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentContentsChanged:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:document.managedObjectContext.persistentStoreCoordinator];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentStateChanged:) name:UIDocumentStateChangedNotification object:document];


        if (![[NSFileManager defaultManager] fileExistsAtPath:[self.mydoc.fileURL path]]) {
            // does not exist on disk, so create it
            [self.mydoc saveToURL:self.mydoc.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
                [self populateTable];//synchronous call. few items are added
                [self iCloudIsReady];
            }];
        } else if (self.mydoc.documentState == UIDocumentStateClosed) {
            // exists on disk, but we need to open it
            [self.mydoc openWithCompletionHandler:^(BOOL success) {
                [self iCloudIsReady];
            }];
        } else if (self.mydoc.documentState == UIDocumentStateNormal) {
            // already open and ready to use
        }
    }

このアプローチに関する私の問題は、2 つのデバイスでアプリを実行しているときに「楽観的ロックの失敗」が発生し続けることです。Apple の Core Data ドキュメントで、この種の問題を「回避」する方法は、マージ ポリシーを NSMergeByPropertyObjectTrumpMergePolicy に設定することであると読みました。

私が見つけられないことの1つは、これを修正する方法です。たとえば、これが発生する可能性がある場合、アプリは少なくともこの動作を認識し、処理する準備ができている必要があります。しかし、私はこれを処理する方法がわかりません。たとえば、競合するオブジェクトを取得して解決するにはどうすればよいですか? このエラーが発生するたびに、ドキュメントを保存しようとすると UIDocumentStateSavingError が発生し始めます。このエラーの発生を止める唯一の方法は、アプリを強制終了して再起動することです。

4

1 に答える 1

0

私はついにこれを理解しました(少なくとも、私はそう思ったと思います)。どうやら、iOS6 +では(iOS5についてはわかりません)、UIManagedDocumentがすべてのマージを処理します。したがって、「mergeChangesFromContextDidSaveNotification:」の呼び出しのみを担当する以下のオブザーバーは、実際には、マージされたばかりのものをマージしていました。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentContentsChanged:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:document.managedObjectContext.persistentStoreCoordinator];

...

- (void)documentContentsChanged:(NSNotification *)notification {
      [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

「mergeChangesFromContextDidSaveNotification:」の呼び出しは、「オプティミスティックロックの失敗」をトリガーする原因となった行でした。私はそれを削除し、すべてが期待どおりに機能し始めました。残念ながら、これは数時間しか続きませんでした。今、私は「iCloud Timed Out」エラーを受け取り続けていますが、これはAppleのせいだと確信しています。

とにかく、たくさんのバグと3つの異なるiCloud + Core Dataアプローチの後、私はiCloudを私のアプリに統合し続けると思います。それはあまりにも不安定でバグがあります。AppleがiOS6でこれを修正できたらいいのにと思います。iCloud+CoreDataは非常に強力なツールですが、残念ながらまだ準備ができていません。

助けてくれたみんなに感謝します。

于 2013-02-07T05:06:03.847 に答える