正如标题所说,如何访问在一个 block 中创建然后需要在另一个 block 中访问的 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];
}];
最佳答案
您不能直接在上下文之间传递托管对象。每个 NSManagedObject
只能通过其自己的上下文访问。
您需要将其 objectID
传递给完成 block ,然后让主上下文通过调用以下方法之一获取对象:
-(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];
}];
关于ios - 你如何在 block 之间访问 NSManagedObject?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29874138/