我最近开始尝试 Core Data 较新的托管对象上下文的 initWithConcurrencyType:NSPrivateQueueConcurrencyType
构造。当使用这种类型的 MOC 时,我们应该使用 performBlock:
或 performBlockAndWait:
来“确保 block 操作在为上下文指定的队列上执行。”
作为此过程的一部分,我将 initWithEntity:insertIntoManagedObjectContext:
的托管对象创建调用移至 performBlock:
block 内,以便在其上运行MOC 的私有(private)队列。
这与 Apple's Core Data Concurrency 中所示的策略匹配文章:
[private performBlock:^{
for (NSDictionary *jsonObject in jsonArray) {
NSManagedObject *mo = ... ; //Managed object that matches the incoming JSON structure
}
NSError *error = nil;
if (![private save:&error]) {
NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
}
}];
我已经found myself在 void
方法中初始化托管对象,这些方法实际上在完成 block 中返回新创建的对象。
+ (void)managedObjectFromJSON:(NSDictionary *)json completion:(void (^)(XYZManagedObject *object))completion;
与简单地从 JSON 解析方法返回对象相比,这种架构引入了复杂性。我似乎还遇到了与此设计相关的并发问题/崩溃,可能是在这些完成 block 构造函数中链接在一起的关系托管对象的异步加载中。
我的每个托管对象都执行如下所示的操作,通过从 performBlock:
block 内调用的完成 block 返回创建的对象。
[managedObjectContextPrivateQueue performBlock:^{
NSEntityDescription *entity = [NSEntityDescription entityForName:@"entity" inManagedObjectContext:managedObjectContextPrivateQueue];
XYZManagedObject *managedObject = [[XYZManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:managedObjectContextPrivateQueue];
[managedObjectContextPrivateQueue save:&error]
completion(managedObject);
}];
或者,是否可以在 performBlock:
block 外部创建托管对象,并且仅将插入/保存操作移至内部?请注意,NSEntityDescription
方法确实需要访问 block 外的 MOC。
NSEntityDescription *entity = [NSEntityDescription entityForName:@"entity" inManagedObjectContext:managedObjectContextPrivateQueue];
XYZManagedObject *managedObject = [[XYZManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
[managedObjectContextPrivateQueue performBlock:^{
[managedObjectContextPrivateQueue insertObject:managedObject];
[managedObjectContextPrivateQueue save:&error]
}];
return managedObject;
或者,也许我应该使用 performBlockAndWait:
等待 block 运行,然后直接从方法而不是从完成 block 返回托管对象。
当托管对象上下文调用应通过 performBlock:
私有(private)队列路由时,应如何创建和返回托管对象?
最佳答案
您可以在 MOC 之外创建托管对象。参见 -[NSManagedObjectContext insertObject:]
。
但是,您可能一般不想这样做。如果你想创建一个有条件的对象,这很有用。例如,如果您有一个表示用户可能编辑的内容的托管对象,您可以创建一个非托管版本用于编辑,并且仅在用户保存更改时插入到 MOC 中。这不是最好的方法,但很有效。
但是,您的问题实际上是关于 MOC 的异步操作。我的意见是,最好的办法是查看每个处理托管对象的 API,并弄清楚如何使它们正确异步。您绝对应该不从方法返回托管对象,除非您知道调用方正在同一 MOC 的 performBlock{AndWait}:
中运行。这是因为无法(可靠地)从创建它们的 MOC 外部访问托管对象。
您可以返回 objectID
,并让调用者获取关联的对象。它通常更乏味且效率更低,但它是跨越 MOC 边界时唯一可靠的解决方案。
关于ios - 是否应该在托管对象上下文的 `performBlock:` 调用中创建核心数据托管对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37260462/