iPhone 编程 - 使用核心数据进行后台保存

Posted

技术标签:

【中文标题】iPhone 编程 - 使用核心数据进行后台保存【英文标题】:iPhone programming - Background saving with core data 【发布时间】:2011-11-28 04:13:01 【问题描述】:

我正在尝试将数据保存到后台线程中的核心数据中,因为保存需要相当长的时间。

我做到了:

[self performSelectorInBackGround:@selector(insertRecord:) withObject:data];

当一切正常时,直到insertRecord 方法中的行命中contextsave:&error。节目接收信号:"SIGABRT"

我做错了吗?当它在主线程中时它工作正常,我只是将代码移动到另一个方法并在后台运行它,它不再工作了。

【问题讨论】:

【参考方案1】:

根据the "Concurrency with Core Data" section of Core Data Programming Guide

推荐使用 Core Data 进行并发编程的模式是 线程限制:每个线程必须有自己的完全私有的 托管对象上下文。

使用线程限制,您不应该传递托管对象或 线程之间的托管对象上下文。

看起来您正在将托管对象传递给后台线程,这是被禁止的。我不知道您是否还尝试在线程之间共享托管对象上下文。

该文档描述了将托管对象传递给其他线程的几种解决方法。您需要实现其中之一。

【讨论】:

我在方法中声明了托管对象上下文,它应该在每个线程上创建一个托管对象上下文。 我的 NSpersistentStoreCoordinator、managedObjectModel 等在 appDelegate 中声明。这是导致问题的原因吗? 你在做[self performSelectorInBackGround:@selector(insertRecord:) withObject:data];。如果data 是托管对象,那是你的问题。【参考方案2】:

这里的问题是托管对象上下文不是线程安全的。如果您的 -insertRecord: 方法使用主线程的托管对象上下文,那么您就是在自找麻烦。

博客Cocoa Is My Girlfriend 有一篇文章Core Data and Threads, Without the Headache 就这个主题提出了一些在后台保存的策略。基本思想是对属于后台线程的上下文进行更改,然后将更改合并到主线程的上下文中。这为您提供了一个最新的上下文,您可以将其保存在后台,同时仍保持主线程的上下文是最新的。

【讨论】:

不,我没有。在 insertRecord 方法中,我声明了一个新的 manageObjectcontext。但参考来自应用程序委托。这也会是个问题吗? 应用委托的参考是什么? 我在应用委托中声明了 NSmanagedObjectModel,NSpersistentStoreCoordinator。我在这样的方法中调用 NSmanageObjectContext: ApplicaionAppDelegate *appDelegate = (ApplicationAppDelegate * ) [[UIApplication sharedApplication] delegate]; NSManagedObjectContext *context = [appDelegate managedObjectContext]; 你只是声明了一个新的指针,但是让它指向应用程序委托的上下文,这无疑是在主线程上创建的。这正是您的问题——跨线程共享单个上下文是不安全的。您不能只在后台线程中获得对应用程序委托上下文的引用;你必须实际创建一个新的上下文。当然,新的上下文会与主线程的上下文不同,这会带来问题。这就是我上面链接的文章的主题。如果您打算在后台保存,请阅读它。

以上是关于iPhone 编程 - 使用核心数据进行后台保存的主要内容,如果未能解决你的问题,请参考以下文章

iphone, 以多对多关系保存数据, 核心数据

iPhone:核心数据保存错误

从 UIImagePickerController 传递图像数据以进行后台处理

在后台线程问题中将服务器数据保存到核心数据

当 iphone 应用程序进入后台或前台状态时,如何保存数据?

核心数据保存到数据库不起作用