2014-08-29 66 views
0

根據蘋果指導原則,爲了在主線程上使用受管對象,它們只需要通過僅限於主線程的上下文來獲取,好吧。以下是我的代碼...使用受管對象上下文與核心數據中的調度隊列

AppDelegate *del = [[UIApplication sharedApplication] delegate]; 

dispatch_queue_t queue1 = dispatch_queue_create("com.MyApp.AppTask",NULL); 
dispatch_queue_t main = dispatch_get_main_queue(); 
dispatch_async(queue1, ^{ 
    NSManagedObjectContext *workerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    workerContext.persistentStoreCoordinator = del.persistentStoreCoordinator; 
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 
    NSArray *managedObject = [workerContext executeFetchRequest:fetchRequest error:nil]; 

    dispatch_async(main, ^{ 
     NSLog(@"%@",managedObject); 
     Person *objperson = [managedObject objectAtIndex:0]; 
     objperson.firstname = @「test」; 
     BOOL s = [workerContext save:nil]; 
     if (s) { 
      NSLog(@"done"); 
     } 
    }); 
}); 

現在根據指南我不能修改或保存由另一個線程創建的託管對象上下文。但上面的代碼工作正常,修改並保存我的對象沒有任何錯誤。因此,我可以修改由另一個線程獲取的MO,甚至可以保存由另一個線程創建的MOC。

請讓我知道如果我這樣做的方式是錯誤的或不是因爲理想情況下我無法從主線程保存後臺線程的MOC。

謝謝。

回答

4

它的錯誤是因爲它的線程不安全的NOT線程不可能與上下文和託管對象交叉線程。

因此,你的微不足道的例子可能在某些情況下工作,但並非所有情況下都是這樣。遲早你會發現這種模式的崩潰。

如果您希望在線程之間訪問對象,則必須跨線程發送objectID

當您使用NSPrivateQueueConcurrencyType創建上下文時,它創建並管理自己的隊列。

你的例子表示更好,因爲

AppDelegate *delegate = [[UIApplication sharedApplication] delegate]; 

    NSManagedObjectContext *workerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

    //set the parent NOT the persistent store coordinator 
    workerContext.parentContext = delegate.managedObjectContext; 

    [workerContext performBlock:^{ 

     NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 
     NSArray *results = [workerContext executeFetchRequest:fetchRequest error:nil]; 

     if (results.count) { 

      Person *person = [results objectAtIndex:0]; 
      person.firstname = @「test」; 

      BOOL success = [workerContext save:nil]; 
      if (success) { 
       NSLog(@"done"); 
      } 

      //you pass ObjectID's NOT managed objects across threads 
      NSManagedObjectID *objectID = [person objectID]; 

      dispatch_async(dispatch_get_main_queue(), ^{ 

       //update your UI here 
       Person *thePerson = (Person *)[[delegate managedObjectContext] objectWithID:objectID]; 
       self.myUIElement.text = person.firstname; 

      }); 
     } 

    }]; 
+1

爲了保持一致,我會設置'[mainManagedObjectContext performBlock:^ {',而不是'dispatch_async(其中mainManagedObjectContext與concurrencyType .MainQueueConcurrencyType初始化)(dispatch_get_main_queue (),^ {' – 2014-08-29 20:59:50

+0

''objectWithID:'應該在上下文的隊列上完成,應該在它之後立即觸發故障,將它們移到主隊列的外部 – quellish 2014-08-29 21:42:39

+0

@pob true,OP正在使用Xcode模板棧,它隱式提供,但你的改變使得一個更正確的例子。 – 2014-08-30 10:37:19

相關問題