2011-11-30 134 views
0

我正在iPad中开发客户端服务器应用程序。我需要保存服务器发送给我的大量数据。它给我一个很长的字符串,我必须把它分解成小记录并保存在核心数据中。它总共发送了20条消息,每条消息大约有100条记录。在线程中保存核心数据

现在的问题是用户必须等待所有消息保存到核心数据中,然后才能解除UI,因为它的所有消息都在主线程中运行。

问题,我可以接收来自服务器的消息,并抛出数据分解并保存到核心数据到线程中吗?当上下文保存时,我不断收到sigbart错误。我检查了核心数据,它在遇到该错误之前节省了大约4条记录。

多个线程可以同时访问/保存到核心数据吗?

对不起,我真的迷路了。尝试了开源的魔法记录,但它仍然有错误。

回答

0

核心数据管理的对象上下文不是线程安全的。虽然您可以拥有单个Core Data存储,但您需要为每个线程创建一个单独的托管对象上下文。如果需要在线程之间传递对管理对象的引用,则需要传递对象ID,然后从本地管理对象上下文中读取对象,而不是尝试传递对象本身。

这样做将使您能够使用核心数据保存在后台。

当保存后台线程时要小心,但应用程序可能在后台线程完成保存之前退出。见this discussion

+0

您的意思是说核心数据一次只能访问一个?我对xcode dev很陌生.. – kraitz

+0

不,我的意思是你通过托管对象上下文访问核心数据,你可以在一个应用程序中拥有多个托管对象上下文,并且每个线程都必须有自己的专用托管对象上下文。 :) –

+0

我在应用程序委托中有一个托管对象上下文。如何在新线程上运行的方法中声明新的方法? – kraitz

0

由于核心数据需要一个管理的每个线程对象上下文,一个可能的解决方案来跟踪每线程上下文的全球经理,然后跟踪保存通知,并传播到所有线程:

假设:

@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]; 
    } 
} 

(为了清晰起见,删除了一些其他方法)