1

내 응용 프로그램에서 JSON 컨텐츠로 요청을 가져 와서 구문 분석하고 CoreData에 저장합니다. 동시에 사용자는 DB와 상호 작용합니다 (읽기 및 쓰기 액세스).여러 병렬 DB 액세스가있는 iOS-App의 디자인

DB에 데이터를 저장 한 후 수신 된 데이터를 기반으로 새 데이터를 만드는 두 번째 작업이 시작됩니다. 나는 Grand Central Dispatch를 사용하여 파싱을 수행하고 데이터를 DB에 저장하려고합니다.

내 문제는 내가 GCD를 사용할 때을 얻을 수 있는데, 이는 Core Data의 비 스레드 안전성으로 인해 발생할 수 있다고 생각합니다. 또 다른 오류는 컨텍스트 performBlockAndWait을 사용할 때 교착 상태가 발생한다는 것입니다.

GCD와 NSMutableContexts을 올바르게 처리하는 앱을 어떻게 디자인해야합니까?

------- 편집 -------- 지금은 내가 스레드 감금 패턴을 사용해야하는 점에 캠 핵심 데이터 프로그래밍 가이드를 읽을 것을

.

내 앱은 현재 다음과 같은 방식으로 구성되어 있습니다. 각각 자신의 컨텍스트를 보유하고있는 몇 명의 관리자가 있습니다. 그러나 여러 스레드를 사용할 때 3 개의 스레드가 동일한 Manager를 호출하여 하나의 컨텍스트가 동시에 3 개의 스레드에 의해 사용된다는 것을 알게되었습니다. 교착 상태가 발생합니다.

- (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; 
} 

이 좋은 생각인가 :이 문제를 해결하려면

는이 같은 threadname하여 컨텍스트를 만들 생각을했다?

답변

2

좋아, 여기에 내가 그것을 해결하는 방법입니다

+(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

와우 ... 그 글에 대한 당신을 사랑해. 굉장해! – yunas

+0

그냥 질문입니다. 더 이상 살아 있지 않은 스레드에 대한 컨텍스트를 어떻게 제거합니까? –