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池。
- dispatch_sync(dispatch_get_global_queue(xxx),任务)同步或asynchronous
- 用于保存核心数据的NSPersistentContainer并发性
- 在iOS 7上使用Private Queue Deadlocks Parent的子级上下文执行块locking和等待
- Swift 3 GCDlockingvariables和block_and_release错误
- 如何在右侧队列上初始化ManagedObjectContext?
- 使核心数据线程安全
- 在不同的线程上调用我的方法有哪些不同的方法?
- 如何确保OperationQueue中的操作一个接一个地完成
- GCD中的并发与串行队列