后台核心数据:使用单独的上下文和通知,但不使用新值更新数据库
Posted
技术标签:
【中文标题】后台核心数据:使用单独的上下文和通知,但不使用新值更新数据库【英文标题】:Core Data in background: Using separate context and notifications, but not updating DB with new values 【发布时间】:2013-10-10 16:37:56 【问题描述】:概述:我有一个在后台运行的刷新过程(只使用 performInBackground 就可以了),其中一部分有数据库更新,所以我有一个单独的 MOC 用于后台线程。然后我使用 didSave 通知合并更改,但在 DB/我的 UI 中看不到这些更新。我在保存之前和之后记录了对象本身,我可以看到属性发生了变化,但是在通知调用的方法中,我在接收到的上下文中记录了对象并且它没有更新的值。我知道其他一些事情可能很丑陋,但只是想弄清楚这个核心数据。我以前只有一个 MOC 并且工作正常(非核心数据应该没问题),但我现在重新设计了一些东西以在后台运行,并希望使用单独的 MOC 的指导。
创建上下文、设置通知、设置属性并保存。保存后,值为0
// this creates context with same PSC as main MOC
NSManagedObjectContext *context = [[MyAppDelegate application] temporaryContext];
[[NSNotificationCenter defaultCenter] addObserver:(MyAppDelegate *)[[UIApplication sharedApplication] delegate]
selector:@selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:context];
NSLog(@"value is %d", [[myObject email] boolValue]); //value is 1
[myObject setEmail:[NSNumber numberWithBool:![[myObject email] boolValue]]];
NSError *error;
if (![context save:&error])
NSLog(@"Error in saving BriefCase object - error:%@" ,error);
NSLog(@"value is %d", [[myObject email] boolValue]); //value is 0 now
在这里,我检查了我发送的 MOC,我看到所有值都是 1。所以当合并发生时,没有更新。如果我看到对象在保存后为 0,断开连接在哪里?
// Called when a ManagedObjectContext performs save operation
- (void)managedObjectContextDidSave:(NSNotification *)notification
NSManagedObjectContext *receivedMOC = [notification object];
NSArray *items = [MyObjectClass getAllMyObjectsInManagedObjectContext:receivedMOC];
for (int i=0; i < [items count]; i++)
NSLog(@"value is %d", [[[items objectAtIndex:i] email] boolValue]);
添加上下文创建代码,可能是问题
- (NSManagedObjectContext *)temporaryContext
NSManagedObjectContext *newContext = [[[NSManagedObjectContext alloc] init] autorelease];
NSPersistentStoreCoordinator *psc = [self.managedObjectContext persistentStoreCoordinator];
[newContext setUndoManager:nil];
[newContext setPersistentStoreCoordinator:psc];
return newContext;
【问题讨论】:
1) 我在您的代码中看不到实际的合并。 - 2) myObject 来自哪里? 非常感谢 mcuh 的回复!是的,抱歉我在此之后进行了合并,但我确信从通知收到的上下文没有更改。合并工作正常,但它没有合并更改导致上下文没有它们。 myObject 是在哪里创建的? 嗨,对不起,错过了这部分,myObject 被传递到方法中。也许这就是问题,因为它与另一个上下文相关联?生病调查它 myObject 与哪个上下文相关联?背景 MOC、主 MOC 还是第三个 MOC? 【参考方案1】:temporaryContext
在每次调用时都会创建一个新的 MOC,因此您似乎实际上使用了 2 个不同的背景 MOC。 myModel
是在不同于
NSManagedObjectContext *context = [[MyAppDelegate application] temporaryContext];
因此保存后者对myModel
中的更改没有影响。
您必须修改您的代码,以便只创建和传递一个临时上下文。
【讨论】:
再次感谢,只是想跟进并说它现在工作!但我时不时地看到一些锁。当我查看锁之前调用的方法时,它访问了主 MOC。我的刷新过程中没有任何东西可以访问它,所有东西都可以访问后台 MOC。但是,我在想我对后台 MOC 所做的更改确实会使用 didSave 通知合并到主 MOC。如果我在执行 mergeChangesFromContextDidSaveNotification 时尝试查询一个 MOC,那会是问题吗?或者它是为了处理这个问题而设计的?【参考方案2】:我没看到你在打电话
[mainMOC mergeChangesFromContextDidSaveNotification:saveNotification];
在处理通知时。这可以解释正在发生的事情。这应该在主线程上调用。
【讨论】:
我认为必须在主上下文中调用 mergeChangesFromContextDidSaveNotification。 @MartinR:谢谢,我就是这个意思;但我试图自定义太多答案而没有考虑太多...... 非常感谢 mcuh 的回复 sergio,抱歉所有问题!在此之后我进行了合并,但我确信从通知中收到的上下文没有更改。合并工作正常,但它没有合并更改导致上下文没有它们。 虽然你提出了一个关于线程的好观点,但合并调用是否总是发生在 main 上?因为我在后台更新那些东西,把主线程留给 UI。由于通知发布在线程 thyre 上,那么这个合并是否会在后台线程上并且是一个问题?这能解释为什么它收到的上下文没有变化吗?这就是最让我困惑的地方 我能做的唯一假设是myObject
不属于您的临时上下文...我还担心performSelectorInBackground
每次都会产生一个新线程-不确定是否是好的...您可能希望每次都创建一个新的临时上下文,或者通过 GCD 管理您的后台处理...以上是关于后台核心数据:使用单独的上下文和通知,但不使用新值更新数据库的主要内容,如果未能解决你的问题,请参考以下文章