在线程中保存核心数据
Posted
技术标签:
【中文标题】在线程中保存核心数据【英文标题】:Core data saving in thread 【发布时间】:2011-11-30 03:49:58 【问题描述】:我正在 iPad 上开发客户端服务器应用程序。我需要保存服务器发送给我的大量数据。它向我发送了一个长字符串,我必须将其分解为小记录并将其保存在核心数据中。它总共向我发送了大约 20 条消息,每条消息大约有 100 多条记录。
现在的问题是用户必须等待所有消息都保存到核心数据中,然后 UI 才能解冻,因为它全部在主线程中运行。
问题,我可以从服务器接收消息,并将数据分解并保存到核心数据中放入线程中吗?保存上下文时,我不断收到 sigbart 错误。我检查了核心数据,在遇到该错误之前它保存了大约 4 条记录。
多个线程可以同时访问/保存到核心数据吗?
对不起,我真的迷路了。试过开源Magical Records,但一直出错。
【问题讨论】:
【参考方案1】:Core Data 托管对象上下文不是线程安全的。虽然您可以拥有一个 Core Data 存储,但您需要为每个线程创建一个单独的托管对象上下文。如果需要在线程之间传递对托管对象的引用,则需要传递对象ID,然后从本地托管对象上下文中读取对象,而不是尝试传递对象本身。
这样做将使您能够使用 Core Data 在后台保存。
在后台线程上保存时要小心,但是应用程序可能会在后台线程完成保存之前退出。见this discussion。
【讨论】:
你的意思是核心数据一次只能访问一个?我对 xcode 开发人员很陌生.. 不,我的意思是您通过托管对象上下文访问核心数据,您可以在一个应用程序中拥有多个托管对象上下文,并且每个线程必须有自己的专用托管对象上下文。 :) 我在应用委托中有一个托管对象上下文。如何在新线程上运行的方法中声明一个新的? 与您声明原始文件的方式相同!然后,当您发送保存消息时,将其发送到新上下文。 所以我产生的每个线程,我都会创建一个新的托管对象上下文。那应该做对吗?【参考方案2】:由于 Core Data 要求每个线程有一个托管对象上下文,一个可能的解决方案是在全局管理器中跟踪每个线程的上下文,然后跟踪保存通知并传播到所有线程:
假设:
@property (nonatomic, strong) NSDictionary* threadsDictionary;
以下是获取托管对象的方法(每个线程):
- (NSManagedObjectContext *) managedObjectContextForThread
// Per thread, give one back
NSString* threadName = [NSString stringWithFormat:@"%d",[NSThread currentThread].hash];
NSManagedObjectContext * existingContext = [self.threadsDictionary objectForKey:threadName];
if (existingContext==nil)
existingContext = [[NSManagedObjectContext alloc] init];
[existingContext setPersistentStoreCoordinator: [self persistentStoreCoordinator]];
[self.threadsDictionary setValue:existingContext forKey:threadName];
return existingContext;
在您的全局管理器的 init 方法中的某个时刻(我使用了单例):
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgroundContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:nil];
然后接收保存通知并传播到所有其他托管上下文对象:
- (void)backgroundContextDidSave:(NSNotification *)notification
/* Make sure we're on the main thread when updating the main context */
if (![NSThread isMainThread])
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
withObject:notification
waitUntilDone:NO];
return;
/* merge in the changes to the main context */
for (NSManagedObjectContext* context in [self.threadsDictionary allValues])
[context mergeChangesFromContextDidSaveNotification:notification];
(为了清楚起见,删除了一些其他方法)
【讨论】:
以上是关于在线程中保存核心数据的主要内容,如果未能解决你的问题,请参考以下文章