根据苹果指南,为了在主线程上使用托管对象,它们只需要被限制在主线程中的上下文获取,好吧没关系。以下是我的代码......
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。
谢谢。答案 0 :(得分: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;
});
}
}];