如果您不使用任何外部库,例如 Magical Record 或 RestKit,而只是使用所有手动的东西,您可以利用新的NSManagedObjectContext
API。
您现在可以使用父子关系嵌套上下文,还可以告诉每个上下文在其自己的线程中执行一个块。因此,我的建议是为您的应用程序提供以下结构:
1)后台保存上下文。这将是唯一直接从数据库保存和读取数据的上下文。
2) 在主线程上初始化的上下文将成为您在应用程序中需要执行的所有操作的访问点,尤其是更新 UI。此上下文将是保存上下文的子级。
3) 根据需要,您将创建在后台线程上执行工作的后台上下文,例如从网络加载数据并在 NSManagedObject 实例中序列化这些数据。该上下文将是主上下文的子上下文。
4) 每次调用-[NSManagedObjectContext save:]
上下文时,还应该在它的 parentContext 上调用相同的方法。为此,您可以在 NSManagedObjectContext 上的类别中使用便利方法,其内容如下:
- (void)saveSelfAndParent {
[self save:NULL];
[self.parentContext performBlock:^{
[self.parentContext saveSelfAndParent];
}];
}
这已经是一个线程安全的配置,您的更改会将更改传播到数据库。请注意,由于保存上下文没有父级(因此 self.parentContext 将为 nil),因此 performBlock: 不会使应用程序崩溃。
这是一个示例,假设您使用 Grand Central Dispatch (GCD) 开始后台工作,您需要执行哪些操作来创建新实体:
dispatch_async(dispatch_async_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType];
context.parentContext = mainContext;
// do some expensive job
...
// initialize a new NSManagedObject instance using the information we calculated
NSManagedObject *myObject = ...;
// once we're done, let's save the context
[context saveSelfAndParent];
});
请注意,我们使用私有队列并发类型 (NSPrivateQueueConcurrencyType) 初始化上下文,它告诉上下文他是后台上下文。这是非常重要的!
就这样!:)
有关详细信息,请参阅NSManagedObjectContext 类参考。