我将核心数据逻辑迁移到RKManagedObjectStore后出现严重问题。我在视图控制器的主线程中设置了一个NSFetchedResultsController,其上下文设置为[NSManagedObject managedObjectContext]:
assert([NSThread isMainThread]);
NSManagedObjectContext* context = [NSManagedObject managedObjectContext];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[Item fetchRequest] managedObjectContext:context sectionNameKeyPath:nil cacheName:@"Master"];
我在上下文中插入对象:
Item* item = [Item object];
item.name = @"Foo";
[[RKObjectManager sharedManager].objectStore save];
但是获取的结果控制器不会收到有关更改的通知。因此,我手动注册了一个通知:
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
NSLog(@"Context changed");
[self.fetchedResultsController performFetch:nil];
[self.tableView reloadData];
}];
我认为这应该没有必要,因为RKManagedObjectStore会在不同的上下文中合并更改。其次,为了删除我试过的Item对象
[item deleteEntity];
这产生了一个错误,表示无法在另一个上下文中删除该对象。这显然是正确的,但是为什么地狱是主线程的上下文不是同一个实例?在删除en实体之前,我也在视图控制器内调用以下内容:
assert([NSThread isMainThread]);
NSManagedObjectContext* sameContext1 = [NSManagedObject managedObjectContext];
NSManagedObjectContext* sameContext2 = self.fetchedResultsController.managedObjectContext;
assert(sameContext1 == sameContext2); //FAILS
查看使用[NSManagedObject managedObjectContext]时调用的RKManagedObjectStore的 managedObjectContext getter实现,应返回每个线程的相同实例:
-(NSManagedObjectContext*)managedObjectContext {
NSMutableDictionary* threadDictionary = [[NSThread currentThread] threadDictionary];
NSManagedObjectContext* backgroundThreadContext = [threadDictionary objectForKey:RKManagedObjectStoreThreadDictionaryContextKey];
...
}
答案 0 :(得分:9)
经过数小时的调试后,我终于找到了这个讨厌的bug。问题是RKObjectManager
包含对RKManagedObjectStore
的引用。但不知何故,当使用ARC时,引用不会保留在[RKObjectManager sharedManager]
实例中并且正在被释放。这会导致刷新线程本地缓存。因此,托管对象上下文合并不起作用,因为在每次访问时都会创建新的托管上下文。修复很容易。只需在App Delegate中对RKManagedObjectStore
进行强有力的引用即可。