我正在开发一个iPad客户端服务器应用程序。我需要保存服务器发送给我的大量数据。它向我发送了一个长字符串,我必须将其分解为小记录并将其保存在核心数据中。它向我发送了大约20条消息,每条消息大约有100条记录。
现在的问题是,在UI解冻之前,用户必须等待将所有消息保存到核心数据中,因为它全部在主线程中运行。
问题,我是否可以从服务器收到消息,并将数据分解并保存到核心数据中?保存上下文时,我不断收到sigbart错误。我检查了核心数据,它在遇到该错误之前保存了大约4条记录。
多个线程可以同时访问/保存到核心数据吗?
抱歉,我真的输了。尝试了开源Magical Records,但它仍然存在错误。答案 0 :(得分:0)
Core Data托管对象上下文不是线程安全的。虽然您可以拥有单个Core Data存储,但您需要为每个线程创建单独的托管对象上下文。如果需要在线程之间传递对托管对象的引用,则需要传递对象ID,然后从本地托管对象上下文中读取对象,而不是尝试传递对象本身。
这样做可以让您使用Core Data在后台保存。
请注意在后台线程上保存但是应用程序可以在后台线程完成保存之前退出。请参阅this discussion。
答案 1 :(得分:0)
由于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];
}
}
(为清楚起见,删除了其他一些方法)