4

去年我使用 RestKit 0.10 在后台无缝下载和保存核心数据对象。然而,当我在 2013 年尝试使用 restkit 时,我注意到他们已经取出了 ActiveRecord 模式,我依靠它来抽象出所有后台保存的不愉快。

我发现 MagicalRecord 框架中存在 ActiveRecord 模式,但我能找到的大部分文档都是针对 2.x 版本的,而我的 cocoapods 安装的是 3.x。

我花了最后 2 个小时搜索,发现了很多已经过时且不再适用于这些新框架的答案。

这就提出了一个问题:使用 2013 年可用的框架在后台保存核心数据对象的标准/最简单的方法是什么?我应该尝试其他一些框架吗?

4

1 回答 1

4

如果您不使用任何外部库,例如 Magical Record 或 RestKit,而只是使用所有手动的东西,您可以利用新的NSManagedObjectContextAPI。

您现在可以使用父子关系嵌套上下文,还可以告诉每个上下文在其自己的线程中执行一个块。因此,我的建议是为您的应用程序提供以下结构:

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 类参考

于 2013-06-17T17:13:09.010 回答