objective-c – Restkit加载的嵌套Core Data实体导致NSObjectInaccessibleException

前端之家收集整理的这篇文章主要介绍了objective-c – Restkit加载的嵌套Core Data实体导致NSObjectInaccessibleException前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_301_1@我正在使用RestKit从我的RoR服务中获取对象,并使用CoreData来保留一些对象(更多的静态类型查找表对象). TasteTag是其中一个持久对象:
#ifdef RESTKIT_GENERATE_SEED_DB
    NSString *seedDatabaseName = nil;
    NSString *databaseName = RKDefaultSeedDatabaseFileName;
#else
    NSString *seedDatabaseName = RKDefaultSeedDatabaseFileName;
    NSString *databaseName = @"Model.sqlite";
#endif

RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:kServerURL];  
manager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:databaseName usingSeedDatabaseName:seedDatabaseName managedObjectModel:nil delegate:self];

.. lots of fun object mapping ..

 RKManagedObjectMapping* tasteTagMapping = [RKManagedObjectMapping mappingForClass:[TasteTag class]];
[tasteTagMapping mapKeyPath:@"id" toAttribute:@"tasteTagID"];
[tasteTagMapping mapKeyPath:@"name" toAttribute:@"name"];
tasteTagMapping.primaryKeyAttribute = @"tasteTagID";
[[RKObjectManager sharedManager].mappingProvider setMapping:tasteTagMapping forKeyPath:@"taste_tags"]; 
[[RKObjectManager sharedManager].mappingProvider addObjectMapping:tasteTagMapping];

.. some more mapping ..

我有从RoR服务器返回的数据,它按预期映射到对象.在RestKit获取请求后,Core Data实体似乎也正常映射:

"<TasteTag: 0x6e87170> (entity: TasteTag; id: 0x6e85d60 <x-coredata://03E4A20A-21F2-4A2D-92B4-C4424893D559/TasteTag/p5> ; data: <fault>)"

问题是当我尝试访问对象的属性时,故障似乎无法解决.起初我只是调用属性,这些属性总是以零形式返回(即使它应该触发错误):

for (TasteTag *tag in self.vintage.tasteTags) {
    [tagNames addObject:tag.name]; //get error of trying to add nil to array   
}

在查看手动触发故障(http://www.mlsite.net/blog/?p=518)之后,我尝试调用[tag willAccessValueForKey:nil],这导致:

Terminating app due to uncaught exception 'NSObjectInaccessibleException',reason: 'CoreData could not fulfill a fault for '0x6e7b060 <x-coredata://03E4A20A-21F2-4A2D-92B4-C4424893D559/TasteTag/p5>''

在.sqlite中查找基于键的实体(TasteTag / p5)确实显示它映射到我期望的那个.

与RestKit相关的其他帖子建议禁用对象缓存(我没有使用),因为这通常是由实体被删除引起的.但是在这个阶段我只是阅读而不是删除,而且我没有缓存.

如果我只是调用[TasteTag allObjects],我可以将所有对象恢复正常,并且它们可以毫无问题地加载.它只是出现故障的情况.

解决方法

我找到了一个适合我的解决方案(我不确定它对你的情况有多适用,但是我将它添加为答案,因为它为我解决了这个(或非常类似的)问题):

几天前,我运行了RKTwitterCoreData示例并注意到它在我的时候工作得非常完美,此时代码非常简单并做了几乎相同的事情,但事实并非如此.我遇到了许多未实现的错误.所以我决定修改我处理RestKit的所有代码,以反映RKTwitterCoreData示例如何做到这一点.

我会把它分成几块,试着帮助你按照我当时的思路(因为我不认为我们的问题是相同的).

我最初的实施假设

由于RestKit可以将对象备份到Core Data,因此我假设这些托管对象可以互换使用.例如,我可以使用Core Data中的对象,其方式与从远程Web服务检索的对象完全相同.我甚至可以将它们合并在一起以获取所有数据.

我错了

我注意到RKTwitterCoreData的代码至少没有以这种方式流动.我的代码中有一大块与他们的代码匹配,但最大的区别在于他们没有将这些对象视为可互换的.实际上,他们从未使用过从远程数据存储中获取的对象.相反,他们只是让它“陷入困境”.我只能假设这意味着它们被添加到Core Data的数据存储中,因为它适用于它们,现在,对我而言.

细节

我的应用程序在修改我的代码以使用此流程后工作.我只能猜测我们看到的无法填充的错误与使用我们从Web服务返回的Core Data支持的对象有关.如果您只是忽略它们然后进行提取,您将获得所有内容(包括最近的请求),并且您不应该得到任何无法填充的错误.

详细说来,如果你看一下RKTwitterViewController,你会注意到第45-61行处理对象的加载:

- (void)loadObjectsFromDataStore {
    [_statuses release];
    NSFetchRequest* request = [RKTStatus fetchRequest];
    NSSortDescriptor* descriptor = [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:descriptor]];
    _statuses = [[RKTStatus objectsWithFetchRequest:request] retain];
}

- (void)loadData {
    // Load the object model via RestKit    
    RKObjectManager* objectManager = [RKObjectManager sharedManager];
    [objectManager loadObjectsAtResourcePath:@"/status/user_timeline/RestKit" delegate:self block:^(RKObjectLoader* loader) {
        // Twitter returns statuses as a naked array in JSON,so we instruct the loader
        // to user the appropriate object mapping
        loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[RKTStatus class]];
    }];
}

一切看起来都很正常(至少与我最初的加载方式相比).但是看一下objectLoader:didLoadObjects:delegate方法

- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
    [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"LastUpdatedAt"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    NSLog(@"Loaded statuses: %@",objects);
    [self loadObjectsFromDataStore];
    [_tableView reloadData];
}

样本甚至没有触摸对象参数! (当然除了NSLog ……)

结论/ TL;博士

不要使用在objectLoader中返回的托管对象:didLoadObjects:就像它们完全由Core Data支持一样.相反,忽略它们并从Core Data重新获取.所有对象,包括上次请求中的对象都在那里.否则,你将得到无法弥补的错误(至少我做过).

猜你在找的C&C++相关文章