Restkit [NSManagedObject managedObjectContext]返回不同的实例

时间:2012-01-20 12:21:40

标签: objective-c ios core-data restkit

我将核心数据逻辑迁移到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];
    ...
}

1 个答案:

答案 0 :(得分:9)

经过数小时的调试后,我终于找到了这个讨厌的bug。问题是RKObjectManager包含对RKManagedObjectStore的引用。但不知何故,当使用ARC时,引用不会保留在[RKObjectManager sharedManager]实例中并且正在被释放。这会导致刷新线程本地缓存。因此,托管对象上下文合并不起作用,因为在每次访问时都会创建新的托管上下文。修复很容易。只需在App Delegate中对RKManagedObjectStore进行强有力的引用即可。