2011-12-23 8 views
2

私は、コアデータを使って大規模な、時には数秒の更新が必要な私の操作をしています。スピナーを表示するだけではなく、エンドユーザーにプログレスバーを表示したいと思っています。しかし、これは、コア・データが主スレッド上で実行することを主張しているため、いくつかの問題を提起します。私はコアデータをdispatch_asyncとバックグラウンドスレッドに入れようとしましたが、悲惨な結果が出ました。問題は、UIKitもメインスレッドで実行したいということです。さらに悪いことに、現在のスレッドが終了した後にのみ更新を行います。これにより、すべての処理が完了するまで、進行状況バーのみが更新されます。コアデータの長期実行プロセスを表示するためにUIを更新するにはどうすればよいですか?

UIを更新して安全にデータを更新するにはどうすればよいですか?

NSArray* items = [[response.data objectForKey:@"result"] objectForKey:@"items"]; 

NSManagedObjectContext* context = [RBGameItemController sharedInstance].managedObjectContext; 

int itemCount = [items count]; 

for (int i = 0; i < itemCount; i++) { 
    float progress = ((float)i/(float)itemCount)*0.95f; 
    self.progressView.progress = 0.5f + progress; 

    id item = [items objectAtIndex:i]; 
    [GameItem gameItemFromDictionary:item inManagedObjectContext:context]; 
} 

NSError* error = nil; 
[context save:&error]; 

答えて

1

コアデータはメインスレッドで作業する必要はなく、スレッドごとにNSManagedObjectContextがあることを確認してください。別のスレッド(NSOperationQueueを使用)に同じバッキングストアを持つ新しいNSManagedObjectContextを作成し、そこで処理を行います。代替スレッドからNSManagedObjectContextを保存すると、メインスレッドのコンテキストがバッキングストアからの変更を取得します。代替スレッドからUIを更新するには、NSObjectのメソッドである

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; 

を使用してください。何かが分からなければ幸運とコメント。

+0

投稿する前にこれを試しましたが、別のmanagedObjectContextからオブジェクトを削除できないというエラーが表示されました。 –

+0

コンテキスト間にNSManagedObjectsを渡すと、そのエラーが発生します。代替スレッドのコンテキストで作業している場合は、変更するオブジェクトのコンテキストを問い合せる必要があります。各スレッドは完全に分離して動作する必要があります。共有できるのはバッキングストアだけです。 –

+0

それはバックグラウンドスレッドに置くのが問題でした。コンテキストをパラメータとして受け入れるようにコードを修正し、私の 'dispatch_async'ブロックで作成した新しいものを渡しました。次に、メインスレッドで実行してUIを更新する新しいGCDスレッドを作成しました。チャームのように働いた! :D –

関連する問題