2

独自の管理対象オブジェクト コンテキストを作成する操作オブジェクトがあります。操作オブジェクトは、基本的にメイン スレッドが UI の側面に集中している間、メイン スレッドの負荷を軽減するために計算を実行します。この操作オブジェクトの MOC は、アプリケーション全体で共通の永続ストアを共有します。

操作の実行中に、バックエンドの変更がメインスレッドの MOC に通知されることがあります。そこで、モデル オブジェクトの削除が発生する可能性がある MOC の変更をマージしようとしました。ごくまれに、私が観察したように、操作オブジェクトがまだ実現されておらず、それらが障害状態にあり、同時にメインスレッドが変更を MOC (および永続ストア) に保存している場合があります。このようなシナリオでアプリがクラッシュします。

標準テキストに従って、私は自分のスレッド専用の MOC を持っています。私の理解によれば、フォールトのデータはスレッドの MOC からアクセスする必要があります。たとえば、同じオブジェクトがストアから削除された可能性がある場合、スレッドの MOC からの障害要求へのアクセスに違いはありますか?

このスタック トレースを参照してください。 ここに画像の説明を入力

これを処理するより良い方法は何でしょうか?

私はこの投稿から理解しています: https://stackoverflow.com/a/5722914/260665スレッドのマネージド オブジェクト コンテキストは、ストアの基礎となる変更を認識しておらず、障害のあるオブジェクトがストアに存在すると予想されます。したがって、次のいずれかを実行することをお勧めします。

  1. NSManagedObjectContextDidSaveNotification通知を使用して、ストアに基になる変更 (削除) がある場合、スレッド内のオブジェクトのコレクションを更新します(From: https://stackoverflow.com/a/5722914/260665 ) 。

  2. MOCNSManagedObjectを使用してプロパティにアクセスする前に、 のレコードがストアに存在するかどうかを確認します (From: https://stackoverflow.com/a/14297708/260665 ) 。-existingObjectWithID

  3. コードで例外を処理しますか? (最後の手段: https://stackoverflow.com/a/15361906/260665から)

NSManagedObject のプロパティが直接アクセスしているわけではないため、ソリューション 1 と 2 を進めることはできません。アプリがクラッシュしているソート記述子を持つ NSFetchedResultController があります。

-(NSMutableArray*)fetchedTaskObjects
{
    if (nil==fetchedTaskObjects_ && self.taskLocalFetchedResultsController && self.persistantTaskFetchedResultsController)
    {
        NSArray *allNonPersistantTasks = [self.taskLocalFetchedResultsController fetchedObjects];
        NSArray *allPersistantTasks = [self.persistantTaskFetchedResultsController fetchedObjects];

        fetchedTaskObjects_ = [[NSMutableArray alloc] init];
        [fetchedTaskObjects_ addObjectsFromArray:allNonPersistantTasks];
        [fetchedTaskObjects_ addObjectsFromArray:allPersistantTasks];
        NSSortDescriptor *tasksSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.mockTaskCounter"
                                                                              ascending:YES];
        NSSortDescriptor *shortTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.shortText"
                                                                                  ascending:YES];
        NSSortDescriptor *headerTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.accountAssignmentText"
                                                                                   ascending:YES];
        [fetchedTaskObjects_ sortUsingDescriptors:[NSArray arrayWithObjects:tasksSortDescriptor, shortTextSortDescriptor, headerTextSortDescriptor, nil]];
    }
    return fetchedTaskObjects_;
}

正しい方法で解決策を見つけるための提案はありますか?

編集: 私が得ているエラー(例外):

CoreData could not fulfill a fault for '0x2b0298a0 <x-coredata://E7E91AFC-5BE6-4996-B28F-92CD115A5D0A/CSTaskRegister/p14746>'

クラッシュするのはどの行ですか?

失敗したマネージド オブジェクトの内部プロパティが、並べ替えの目的で並べ替え記述子によってアクセスされようとすると、並べ替え記述子のいずれかでクラッシュします。これはスレッドであるため、基になるオブジェクトがストアで削除された正確な時期はわかりません。そのため、私の統計計算コードでもスレッドクラッシュが発生することがあります。

なぜ 2 つの FRC の結果を組み合わせるのですか?

プロジェクトは当初、これら 2 つのケースに対して異なる MOC で開始されたため、MOC は単一ですが、差別化は依然として残っています。しかし、個別の FRC を独自の目的で使用することは問題ではないと思います。

4

2 に答える 2

1

操作の MOC をマージできない場合、または操作の MOC に触れたくない場合 (現在使用中など)、操作データの更新シリアル化されることを保証する必要があります。

アイデアは、操作が実行されているとき、データの状態の現在のビューが一定であると想定しているため、変更してはならないということです。

これを保証するには、いくつかの選択肢があります。

オペレーションの実行中に update-request を受け取り、かつ共有永続ストアを含むデータをすぐに更新したい場合は、まずオペレーションをキャンセルし、オペレーションが完了するまで待機する必要があります (その後オペレーションの MOC でアクセスは発生しません)。 )。次に、メイン MOC のデータの更新を開始します。永続ストアを含めて更新が完了したら、データの実際の状態を反映して、新しく初期化または適切にマージされた MOC を使用して操作を再開できます。

同様に、実行中の操作が完了するまで更新リクエストを延期することもできます。

于 2013-10-23T11:31:57.313 に答える