Ale*_*one 19 iphone concurrency core-data objective-c ios
由于并发和多线程,我随机崩溃核心数据.我知道核心数据不是线程安全的.我还找到了关于如何创建ThreadedDataService以及为每个线程实例化单独上下文的其他几个答案.
这对我来说有点太多了,所以我试图找到一个更简单的方法.
我目前正在尝试的解决方案很简单:通过主线程保存数据.但是,现在出现了一个新问题:死锁.该应用程序变得无法响应,因为我对新NSManagedObject的每次插入后都会调用save.(这是我最好的猜测).
阅读App Delegate文档,我注意到它建议我在applicationWillTerminate中保存上下文.
我的问题是:对于每分钟插入新事件的长时间运行操作,并且用户不需要立即看到传播到所有控制器的更新,何时是保存上下文的好时机? 我觉得为每条记录保存上下文可能有点矫枉过正?
-(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];
}
}
}
Run Code Online (Sandbox Code Playgroud)
我为所有托管对象定义了这些方法,如果我每10-15分钟在主线程上调用这样的方法来保存挂起的更改就足够了,而不是在每次插入记录后这样做?
-(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]);
}
}
Run Code Online (Sandbox Code Playgroud)
阅读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 ;
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
mac*_*die 17
您不必在过程的早期保存上下文,尤其是当您想要在之后修改对象时.
在大多数情况下,您应该NSManagedObjectContext为要在数据库上执行的更改创建单独的.因此,在其上创建对象,填写所需的属性,然后使用主上下文发送save和执行整个mergeChangesFromContextDidSaveNotification:技巧(最有可能在主线程上运行,因此使用performSelectorOnMainThread...消息).
默认情况下,创建并返回的对象NSManagedObjectContext是自动释放的.例如,如果您已创建新对象并希望在表单中对其进行编辑,则可以setRetainsRegisteredObjects:在创建对象之前使用YES 调用托管对象上下文,因此它将保留创建的对象,直到您完成它为止.请记住,不建议NSManagedObject您自己管理s'生命周期 - 您应该让它自己NSManagedObjectContext做.所以,考虑到这一点,你不必保留NSManagedObject.在保存操作之后,它将被上下文取消注册并从内存中删除.您无需任何操作.
如果你返回NSManagedObjectID(使用[object objectID])而不是对象本身可能会更好.它允许通过上下文安全地处理对象,并且如果需要对象进行进一步编辑或数据检索(例如,来自其他上下文),则它们可以单独从存储中获取它.
即使您不保存上下文,新创建的对象也在那里,然后您可以决定是否要保留该对象.
另一方面,在保存之后,如果上下文仍然存在,它可能会NSManagedObjectID从内存缓存中返回给定给您的对象- 而不会触及数据库.
在另一方面;),在你的情况下,你可以非常安全地返回对象,因为NSManagedObjectContext创建它仍然存在,所以该对象仍然存在,虽然已经在自动释放池中.
| 归档时间: |
|
| 查看次数: |
22904 次 |
| 最近记录: |