私はGrand Central Dispatch(GCD)とCore Dataの初心者です。40.000レコードをCore Dataに追加している間、UIがロックされないように、CGDでCore Dataを使用するためにあなたの助けが必要です。
CDはスレッドセーフではないことを知っているので、いくつかの記事から理解できる限り、別のコンテキストを使用し、データを保存してコンテキストをマージする必要があります。
私がまだできなかったことは、ピースをまとめることです。
だから、私のコードでは、その方法についてあなたの助けが必要です。
私が持っています:
/*some other code*/
for (NSDictionary *memberData in arrayWithResult) {
//get the Activities for this member
NSArray *arrayWithMemberActivities = [activitiesDict objectForKey:[memberData objectForKey:@"MemberID"]];
//create the Member, with the NSSet of Activities
[Members createMemberWithDataFromServer:memberData
andActivitiesArray:arrayWithMemberActivities
andStaffArray:nil
andContactsArray:nil
inManagedObjectContext:self.managedObjectContext];
}
これをバックグラウンドで動作するように変換し、保存が完了したら、40.000オブジェクトの保存中にUIをブロックせずにデータを保存してUIを更新するにはどうすればよいですか?
ここにあなたが試す良い例があります。ご不明な点がございましたら、お気軽にご連絡ください。
self.mainThreadContext... // This is a reference to your main thread context
NSPersistentStoreCoordinator *mainThreadContextStoreCoordinator = [self.mainThreadContext persistentStoreCoordinator];
dispatch_queue_t request_queue = dispatch_queue_create("com.yourapp.DescriptionOfMethod", NULL);
dispatch_async(request_queue, ^{
// Create a new managed object context
// Set its persistent store coordinator
NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init];
[newMoc setPersistentStoreCoordinator:mainThreadContextStoreCoordinator]];
// Register for context save changes notification
NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
[notify addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:newMoc];
// Do the work
// Your method here
// Call save on context (this will send a save notification and call the method below)
BOOL success = [newMoc save:&error];
if (!success)
// Deal with error
[newMoc release];
});
dispatch_release(request_queue);
そして、コンテキスト保存通知に応じて:
- (void)mergeChanges:(NSNotification*)notification
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.mainThreadContext mergeChangesFromContextDidSaveNotification:notification waitUntilDone:YES];
});
}
また、バックグラウンドスレッドコンテキストを使い終わったら、通知センターからオブザーバーを削除することを忘れないでください。
[[NSNotificationCenter defaultCenter] removeObserver:self];
これは、GCDとUIを最も簡単に説明したスニペットです。 doWorkを、CoreDataを機能させるコードに置き換えることができます。
CDとスレッドの安全性に関して、GCDの優れた点の1つは、アプリケーション(サブシステム)の領域からセクションを分割して、それらを同期し、同じキューで確実に実行されるようにすることです。すべてのCoreData作業をcom.yourcompany.appname.dataaccessという名前のキューで実行できます。
サンプルには、長時間実行中の作業を起動するボタンとステータスラベルがあり、bg作業の実行中にスライダーを移動できることを示すためにスライダーを追加しました。
// on click of button
- (IBAction)doWork:(id)sender
{
[[self feedbackLabel] setText:@"Working ..."];
[[self doWorkButton] setEnabled:NO];
// async queue for bg work
// main queue for updating ui on main thread
dispatch_queue_t queue = dispatch_queue_create("com.sample", 0);
dispatch_queue_t main = dispatch_get_main_queue();
// do the long running work in bg async queue
// within that, call to update UI on main thread.
dispatch_async(queue,
^{
[self performLongRunningWork];
dispatch_async(main, ^{ [self workDone]; });
});
// release queues created.
dispatch_release(queue);
}
- (void)performLongRunningWork
{
// simulate 5 seconds of work
// I added a slider to the form - I can slide it back and forth during the 5 sec.
sleep(5);
}
- (void)workDone
{
[[self feedbackLabel] setText:@"Done ..."];
[[self doWorkButton] setEnabled:YES];
}
このブログ投稿には、コアデータの同時実行性とサンプルコードの詳細な説明があります。 http://www.duckrowing.com/2010/03/11/using-core-data-on-multiple-threads/
チェックできる別の情報源を追加する
最近更新されたAppleのiOS開発者ライブラリのサンプルコード(2013-06-09)
コアデータプログラミングガイドに記載されている最初の推奨パターンに従って、マルチスレッド環境でコアデータを使用する方法を示します。
SeismicXMLサンプルに基づいて、世界中の最近の地震に関するデータを提供する米国地質調査所(USGS)からRSSフィードをダウンロードして解析します。このサンプルの違いは、Core Dataを使用して永続的に地震を保存することです。アプリを起動するたびに、新しい地震データがダウンロードされ、NSOperationで解析されます。NSOperationは重複をチェックし、新しく作成された地震を管理対象オブジェクトとして保存します。
Core Dataを初めて使用する場合は、SeismicXMLサンプルをこのサンプルと比較して、アプリケーションにCore Dataを導入するために必要な要素を確認しておくと役立ちます。
これを行うには、永続ストアコーディネーターを新しいコンテキストに接続するよりもはるかに簡単です。これは、スレッドセーフでもありません。
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrency];
[context setParentContext:<main thread context here>];
[context performBlock:^{
...
// Execute all code on current context
...
}];
NSError *error = nil;
[context save:&error];
if (!error) {
[context.parentContext save:&error];
if (error) {
NSLog(@"Could not save parent context: %@", error);
}
}
else {
NSLog(@"Could not save context: %@", error);
}
マルチコンテキストコアデータの使用方法に関する素晴らしいチュートリアル:
したがって、これに対する選択された答えは、ほぼ2年前のものであり、いくつかの問題があります。
-編集-
#3をさらに詳しく見る-waitUntilDone:YESはマネージコンテキストオブジェクトの有効なmethodSignatureではないので、それはどのように機能しますか?