3

私はアップルのドキュメントを読んでいますが、AIが答えを見つけることができないという質問があります。メイン スレッドの子コンテキストとプライベート スレッドの親コンテキストの 2 つのネストされたコンテキストを持つ UIManagedDocument オブジェクトがあります。次に、サーバー側があります。そのため、データがサーバーから到着したら、バックグラウンド スレッドで管理ドキュメントに挿入したいと考えています。

非同期キューを作成し、そこに NSManagedObjectContext を作成し、メインスレッドで作成された親 UIManagedDocument の子コンテキストとして設定するのはスレッドセーフですか?

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
     //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [backgroundContext setParentContext:self.eventDatabase.managedObjectContext]; // is this thread safe?

    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");


});
dispatch_release(fetchQ);

言い換えれば、メインスレッドで作成されたプライベートスレッドの親で作成されたコンテキストに割り当てることはスレッドセーフですか?

4

2 に答える 2

4

プライベート同時実行タイプを使用しています。つまり、(performBlock を介して) 独自のキューでコードを実行する必要があります。だから、それをやりたいなら、このようにすればいいのです...

NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.parentContext = self.eventDatabase.managedDocument;
backgroundContext.performBlock:^{
    //here goes some code for downloading data from the server
    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");

    // Calling save on the background context will push the changes up to the document.
    NSError *error = nil;
    [backgroundContext save:&error];

    // Now, the changes will have been pushed into the MOC of the document, but
    // the auto-save will not have fired.  You must make this call to tell the document
    // that it can save recent changes.
    [self.eventDatabase updateChangeCount:UIDocumentChangeDone];
});

キューを自分で管理したい場合は、おそらく制限 MOC を使用する必要があります。NSConfinementConcurrencyType で初期化するか、標準の init で初期化する必要があります。これがデフォルトであるためです。すると、こんな感じに・・・。

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
    backgroundContext.parentContext = self.eventDatabase.managedDocument;

    //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] init];

    // Everything else is as in the code above for the private MOC.
});
dispatch_release(fetchQ);
于 2012-04-10T17:22:09.880 に答える
0

Andrew managedobjectcontext はスレッドセーフではありません。あなたが望むものを達成するには、子の管理されたコンテキストを作成し、あなたの仕事をしてから、子と親のコンテキストに変更を保存してください。保存は変更を 1 レベル上げるだけであることを覚えておいてください。

NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[addingContext setParentContext:[self.fetchedResultsController managedObjectContext]];

[addingContext performBlock:^{
    // do your stuffs
    [addingContext save:&error];

    [parent performBlock:^{
        [parent save:&parentError];
    }];
}];
于 2013-02-19T16:22:39.633 に答える