2014-08-29 65 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

相关问题