0

プライベート コンテキストにログインした直後に (メイン スレッドのブロックを回避するため) 、少し重いコア データ挿入作業(たとえば A)を実行しています。これが完了する前に、残念ながらコードのどこかに挿入作業(B など)があります (重くはない) が、これは不可欠であり、プライベート コンテキストを使用して保存します。

問題:どこにでもレコードを保存しているときに、それらがすでにDBにあるかどうかを確認します(一意のレコードを確保するため)。タスク A で「保存」すると、他のプロセス B はすでに重複レコードを書き込んでいました。

解決策を探していますが、次の 2 つの選択肢があります。

  1. 2 番目のタスクが最初のタスクを待機するようにする (別のスレッドでディスパッチし、完了するまで待機する)
  2. お願いします!!

編集: 問題は同時実行性ではなくマージに関連していることが判明しました。マージにより重複レコードが作成され、同時実行性は問題ありません。スローされるエラーは次のとおりです。

NSCocoaErrorDomain Code=133020

更新: マージの問題は上書きマージ ポリシーで修正されました

4

1 に答える 1

1

質問で自分で言ったのですが、2 つの異なる場所から保存しているため、オブジェクトが複製されています。

1 つの戦略は、同じ NSManagedObjectContext を使用してすべての書き込みを実行することです。書き込みを実行するために複数のバックグラウンド コンテキストを作成する必要はほとんどありません (書き込みに時間がかかる場合を除きます)。

はっきり言って、2 つの書き込み操作で同じオブジェクトを書き込む可能性があります。すべての書き込みを単一のインターフェイスで管理すると、このインターフェイスは書き込み用のプライベート コンテキストを保持します。コンテキストはシリアル キューであるため、同じオブジェクトを 2 回書き込むことができないことを保証できます (重複のチェックがしっかりしていると仮定します)。

したがって、インターフェースは次のようになります。

@interface CoreDataManager : NSObject
+ (CoreDataManager*)sharedManager;
- (void)performWriteWithBlock:(void (^)(NSManagedObjectContext *writeContext))writeBlock;
@end

@implementation CoreDataManager
+ (CoreDataManager *)sharedManager {
    static dispatch_once_t once;
    dispatch_once(&once, ^ {
        self.writeContext = [[self class] createBackgroundPersistanceObjectContext];
    });
    return sharedManager;
}

- (void)performWriteWithBlock:(void (^)(NSManagedObjectContext *writeContext))writeBlock {
    if (writeBlock) {
        writeBlock(self.writeContext);
        [self.writeContext save:nil];
    }
}

+ (NSManagedObjectContext *)createBackgroundPersistanceObjectContext {
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [context setPersistentStoreCoordinator:coordinator];
    context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
    context.undoManager = nil;
    return context;
}
@end

それにもかかわらず、インターフェイスを定義する方法はたくさんありますが、重要なのは、コア データの読み取りと書き込みを処理する単一のインターフェイスを用意することです。

于 2014-11-13T12:28:56.700 に答える