iOS核心数据何时保存上下文?

由于并发性和multithreading,我的核心数据随机崩溃。 我知道核心数据不是线程安全的。 我还发现了一些关于如何创buildThreadedDataService并为每个线程实例化单独的上下文的其他答案。

这一点对于我来说现在有点太多了,所以我试图find一个更简单的方法。

我现在正在尝试的解决scheme很简单: 通过主线程保存数据。 但是,现在出现了一个新的问题: 僵局 。 该应用程序变得没有响应,因为我的每个插入一个新的NSManagedObject紧跟着一个调用来保存。 (这是我最好的猜测)。

阅读App Delegate文档,我发现它build议我在applicationWillTerminate中保存上下文。

我的问题是这样的: 对于每分钟插入一个新事件的长时间运行的操作,并且用户不需要立即看到传播到所有控制器的更新,什么时候是我保存上下文的好时机? 我觉得每个logging的保存环境可能是一个矫枉过正的感觉?

-(void)insertNewEvent { // Create a new instance of the entity managed by the fetched results controller. NSManagedObjectContext *context = [self.fetchedResultsController.managedObjectContext]; NSEntityDescription *entity = [[self.fetchedResultsControllerfetchRequest] entity]; Event*newManagedObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; //use accessor methods to set default values // Save the context. > IS THIS REALLY NEEDED HERE? NSError *error = nil; if (![context save:&error]) { }else { if(newManagedObject!=nil) { currentState= newManagedObject; [currentRecord addEvent:newManagedObject]; //Is this call needed? [self saveApplicationRecords]; } } } 

我有这样的方法定义为我的所有pipe理对象,这是足够的,如果我每10-15分钟在主线程上调用这样的方法来保存挂起的更改,而不是每次logging插入后这样做?

 -(void)saveApplicationRecords { NSLog(@"saveApplicationRecords"); NSManagedObjectContext *context = [self.applicationRecordsController.managedObjectContext]; // Save the context. NSError *error = nil; if (![context save:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); } } 

在阅读macbirdie的回应之后还有一个额外的问题:这种核心数据合法吗?

 -(Event*)insertAndReturnNewEventWithDate:(NSDate*)date_ type:(int)type { NSManagedObjectContext *context = [self.dreamEventsController managedObjectContext]; NSEntityDescription *entity = [[self.dreamEventsController fetchRequest] entity]; DreamEvent *newManagedObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; //handle properties NSError *error = nil; if (![context save:&error]) { return nil; }else { return newManagedObject ; } } 

谢谢!

您不必在stream程的早期保存上下文,尤其是当您想要在之后修改对象时。

在大多数情况下,您应该为您要在数据库上执行的更改创build单独的NSManagedObjectContext 。 因此,创build对象,填写所需的属性,然后发送save并执行整个mergeChangesFromContextDidSaveNotification:与主要上下文(最有可能运行在主线程,所以使用performSelectorOnMainThread …消息)窍门。

默认情况下,由NSManagedObjectContext创build并返回的对象是自动释放的。 如果您创build了一个新对象,并且想要在表单中编辑它,则可以在创build对象之前调用setRetainsRegisteredObjects:与托pipe对象上下文的YES,以便在完成之前保留创build的对象用它。 请记住,不build议您自己pipe理NSManagedObject的生命周期 – 您应该让NSManagedObjectContext执行它。 所以,记住这一点,你不必保留NSManagedObject 。 在保存操作之后,它由上下文取消注册并从内存中移除。 没有什么是你需要的。

回答更新的问题部分

如果你返回NSManagedObjectID (使用[object objectID] )而不是对象本身,那可能会更好。 它允许通过上下文安全地处理对象,并且如果需要对象进行进一步编辑或数据检索(例如从其他上下文),则可以单独从商店获取它。

即使不保存上下文,新创build的对象也在那里,然后您可以决定是否要保留该对象。

另一方面保存后,如果上下文仍然存在,它可能会从内存caching中返回给定NSManagedObjectID的对象,而不会触及数据库。

另一方面),在你的情况下,你几乎可以安全地返回对象,因为NSManagedObjectContext创build它仍然存在,所以对象仍然存在,虽然已经在autorelease池。