1

私のアプリケーションでは、JSONコンテンツを要求を取得し、解析してCoreDataに格納しています。同時に、ユーザーはDBと対話しています(読み書きアクセス)。複数の並列DBアクセスを持つiOS-Appの設計

DBにデータを格納した後、受信したデータに基づいて新しいデータを作成する第2のタスクが開始されます。私はGrand Central Dispatchを使って解析を行い、データをDBに保存します。

私の問題は、GCDを使用するとが得られ、Core Dataのスレッドセーフではないと思われます。他のエラーは、コンテキストperformBlockAndWaitを使用するとデッドロックが発生することです。

GCDとNSMutableContextsを適切に処理するアプリをデザインするにはどうすればよいですか?

------- EDIT --------

今、私は私がスレッド閉じ込めパターンを使用する必要がポイントにカムコアデータプログラミングガイドを読んでいること。

私のアプリケーションは現在、このように構成されています。それぞれ独自のコンテキストを持つ2つのマネージャがあります。しかし、いくつかのスレッドを使用する場合、3つのスレッドが同じマネージャを呼び出し、1つのコンテキストが同時に3つのスレッドによって使用されることになります。これにより、デッドロックが発生します。この問題を解決するには

私はこのようなのthreadNameでコンテキストを作成するためのアイデアに来た:

- (NSManagedObjectContext *)createManagedObjectContextWithTreadName:(NSString*) threadname { 

    if([NSThread currentThread].name.length ==0){ 
     [NSThread currentThread].name = threadname; 
    } 

    NSManagedObjectContext *context = nil; 
    context = [self.contextStore objectForKey:threadname]; 

    if(!context){ 
     NSLog(@"Creating context for threadname: %@",threadname); 

     NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator; 
     if (coordinator != nil) 
     { 
      context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
      context.persistentStoreCoordinator = coordinator; 
      context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy; 

      NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
      [nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:context]; 
      [self.contextStore setValue:context forKey:threadname]; 
     } 
    } 
    return context; 
} 

は、これは良いアイデアですか?

答えて

2

[OK]を、ここでは、私はそれを解決する方法である:

+(NSManagedObjectContext *)managedObjectContext { 
    AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate; 
    NSManagedObjectContext *moc = delegate.managedObjectContext; 

    NSThread *thread = [NSThread currentThread]; 

    if ([thread isMainThread]) { 
     return moc; 
    } 

    // a key to cache the context for the given thread 
    NSString *threadKey = [NSString stringWithFormat:@"%p", thread]; 

    // delegate.managedObjectContexts is a mutable dictionary in the app delegate 
    NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts; 

    if ([managedObjectContexts objectForKey:threadKey] == nil) { 
     // create a context for this thread 
     NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

     threadContext.persistentStoreCoordinator = [moc persistentStoreCoordinator]; 
     threadContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy; 

     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
     [nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:threadContext]; 

     // cache the context for this thread 
     [managedObjectContexts setObject:threadContext forKey:threadKey]; 
     //NSLog(@"MocCount: %d",managedObjectContexts.count); 
    } 

    return [managedObjectContexts objectForKey:threadKey]; 
} 

+ (void)mergeChangesFromMOC:(NSNotification *)aNotification { 

    //NSLog(@"Performing a merge of managed object context in class %@",[self class]); 

    @try { 
     AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate; 
     NSManagedObjectContext *moc = delegate.managedObjectContext; 
     [moc mergeChangesFromContextDidSaveNotification:aNotification]; 


     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
     [nc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:[aNotification object]];  
    } 
    @catch (NSException * e) { 
     NSLog(@"Stopping on exception: %@", [e description]); 
    } 
    @finally {} 
} 
どこでも私は、私は[ContainingClass managedObjectContext]聞いて、コンテキストを必要

し、メインスレッドまたは私は午前のスレッドのコンテキストを取得するときにマージを。これがメインスレッドで実行される必要があります。

+0

wow ...あなたはその投稿を愛しています。驚くばかり ! – yunas

+0

ちょうど質問ですが、もはや生きていないスレッドのコンテキストをどうやって削除しますか? –