1

在我的應用程序中,我使用JSON內容獲取請求,解析它們並將它們存儲在CoreData中。與此同時,用戶正在與數據庫交互(讀寫訪問)。具有多個並行數據庫訪問的iOS應用程序的設計

將數據存儲到數據庫之後,將根據接收到的數據啓動第二個任務以創建新數據。我將使用Grand Central Dispatch來解析並將數據存儲到數據庫。

我的問題是,當使用GCD時,我得到一個EXC_BAD_ACCESS,這可能是由於我假設的核心數據的非線程安全性導致的。另一個錯誤是我在使用上下文performBlockAndWait時遇到了死鎖。

我應該如何設計我的應用程序,它具有適當的GCD處理和NSMutableContexts

------- --------編輯

現在,我已經閱讀了核心數據編程指南我凸輪,我必須使用線程約束模式的地步。

我的應用程序目前的結構是這樣的:我有幾個管理員,每個人都擁有自己的上下文。但是,當使用多個線程時,我來到了3個線程調用同一個Manager的位置,這意味着一個上下文被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

確定 - 這裏是我如何解決它:

+(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 2012-09-09 23:15:15

+0

只是一個問題,如何刪除不再活動的線程的上下文? – 2012-12-06 11:00:01

相關問題