去年我使用RestKit 0.10在后台无缝下载和保存核心数据对象。然而,当我在2013年尝试使用restkit时,我注意到他们已经取出了ActiveRecord模式,我依赖它来消除所有背景保存的不愉快。
我发现ActiveRecord模式存在于MagicalRecord框架中,但我找到的大多数文档都是针对2.x版本,而我的cocoapods安装了3.x.
我花了最近2个小时进行搜索,发现很多答案确实已经过时,不再适用于这些新框架。
这提出了一个问题:使用2013年提供的框架处理在后台保存核心数据对象的标准/最简单方法是什么?我应该尝试其他框架吗?
答案 0 :(得分:4)
如果您不使用任何外部库(如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 Class Reference。