与标题一样,如何访问已在一个块中创建的NSManagedObject,然后需要在另一个块中访问。我有以下实现,并想知道它是否正确。
__block Person *newPerson;
@weakify(self);
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
newPerson = [Person MR_createInContext:localContext];
newPerson.name = @"Bob";
} completion:^(BOOL success, NSError *error) {
@strongify(self);
// Called on main thread
PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:newPerson];
[self.navigationController pushViewController:personVC animated:YES];
}];
我是否正确无需从完成处理程序中的localContext访问newPerson,因为它将在主线程上执行?
修改
看起来以下是建议的方式:
__block NSManagedObjectID *newPersonObjectID;
@weakify(self);
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
Person *newPerson = [Person MR_createInContext:localContext];
newPerson.name = @"Bob";
newPersonObjectID = newPerson.objectID;
} completion:^(BOOL success, NSError *error) {
@strongify(self);
// Called on main thread
Person *savedPerson = [[NSManagedObjectContext MR_defaultContext] objectWithID:newPersonObjectID];
PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:savedPerson];
[self.navigationController pushViewController:personVC animated:YES];
}];
解决方案
这个答案和评论导致以下解决方案。 临时ID正在被保存时被分配给对象,因此当尝试使用TempID获取对象时,会发生异常。
不是创建一个全新的获取请求,而是要求上下文尽早获取永久ID,而不是获取对象的永久ID。例如:
__block NSManagedObjectID *newPersonObjectID;
@weakify(self);
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
Person *newPerson = [Person MR_createInContext:localContext];
newPerson.name = @"Bob";
[localContext obtainPermanentIDsForObjects:@[newPerson] error:NULL];
newPersonObjectID = newPerson.objectID;
} completion:^(BOOL success, NSError *error) {
@strongify(self);
// Called on main thread
Person *savedPerson = [[NSManagedObjectContext MR_defaultContext] objectWithID:newPersonObjectID];
PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:savedPerson];
[self.navigationController pushViewController:personVC animated:YES];
}];
答案 0 :(得分:2)
您无法在上下文之间直接传递托管对象。每个NSManagedObject
只能通过自己的上下文访问。
您需要将其objectID
传递给完成块,然后让主上下文通过调用以下方法之一来获取对象:
-(NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID
这将为具有指定objectID的对象创建一个错误,无论它是否实际存在于商店中。如果它不存在,那么触发故障的任何事情都将失败并出现异常。
-(NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID
error:(NSError **)error
这将从具有该ID的商店中获取对象,或者如果它不存在则返回nil。与objectWithID
不同,该对象不会出现故障;将检索其所有属性。
在任何一种情况下,您的本地上下文必须已将Person
对象保存到商店,以便主要上下文能够获取它。
有关objectID
的更多详细信息,请参阅Core Data Programming Guide
按用户提问提问
这个答案和评论会导致正确的解决方案。 临时ID正在被保存时被分配给对象,因此在尝试使用TempID获取对象时会发生异常。
不是创建一个全新的获取请求,而是要求上下文尽早获取永久ID,而不是获取对象的永久ID。例如:
__block NSManagedObjectID *newPersonObjectID;
@weakify(self);
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
Person *newPerson = [Person MR_createInContext:localContext];
newPerson.name = @"Bob";
[localContext obtainPermanentIDsForObjects:@[newPerson] error:NULL];
newPersonObjectID = newPerson.objectID;
} completion:^(BOOL success, NSError *error) {
@strongify(self);
// Called on main thread
Person *savedPerson = [[NSManagedObjectContext MR_defaultContext] objectWithID:newPersonObjectID];
PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:savedPerson];
[self.navigationController pushViewController:personVC animated:YES];
}];
答案 1 :(得分:1)
您应该访问块外部的objectID(例如,在主线程上),然后在块中使用它。类似的东西:
NSManagedObjectID *objectID = appDelegate.myObject.objectId;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// use objectID here.
}