【发布时间】:2015-03-16 11:57:35
【问题描述】:
我有一个拥有用户的应用。用户属于一个帐户。一个帐户可以有多个项目,并且在这些项目中,Account.Users 的一个子集通过“协作”对象分配为协作者。我使用 RestKit 检索此信息并将其存储在 CoreData 中,但是我在连接关系时遇到了一些麻烦 - 可能是由于对象的存储顺序。
我的项目 JSON 看起来像这样:
{
"id": 1,
"name": "Some Project Name",
"collaborations": [
{
"id": 1,
"collaborator_id": 1,
"permission_group_ids": [ 1, 2 ]
},
{
"id": 2,
"collaborator_id": 2,
"permission_group_ids": [ 2, 3 ]
}
],
"permission_groups": [
{
"id": 1,
"name": "Admin"
},
{
"id": 2,
"name": "Manager"
},
{
"id": 3,
"name": "Employee"
}
]
}
现在,如您所见,我已经嵌套了对该项目特定的其他对象的引用。每个协作者都属于特定于项目的一组权限组。我的协作映射(该类在内部称为ProjectCollaborator)设置如下。我成功地在应用程序的其他地方使用了类似的代码。
// These mappings (and others) work fine.
[map addAttributeMappingsFromDictionary:@{@"permission_group_ids" : @"permissionGroupIds"}];
[map addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:@"collaborator" withMapping:[User collaboratorMapping]]];
// This mapping works fine in other places, but not here.
NSEntityDescription *entity = [NSEntityDescription entityForName:[self entityName] inManagedObjectContext:[RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext];
NSRelationshipDescription *groupRelationship = [entity relationshipsByName][@"permissionGroups"];
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:groupRelationship attributes:@{@"permissionGroupIds" : @"serverId"}];
[map addConnection:connection];
我的请求设置如下。
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:[RKObjectManager sharedManager].responseDescriptors];
共享管理器上的响应描述符是这样添加的:
[[RKObjectManager sharedManager] addResponseDescriptorsFromArray:@[...
[RKResponseDescriptor responseDescriptorWithMapping:[Project showResponseMapping] method:RKRequestMethodGET pathPattern:@"projects/:serverId" keyPath:@"project" statusCodes:successCodes]
...]];
这是Project showResponseMapping的相关部分:
+(RKEntityMapping *) showResponseMapping
{
static RKEntityMapping* map = nil;
if (map == nil)
{
map = [RKEntityMapping mappingForEntityForName:[self entityName] inManagedObjectStore:[[RKObjectManager sharedManager] managedObjectStore]];
map.identificationAttributes = @[ @"serverId" ];
[map addAttributeMappingsFromDictionary:@{ @"name" : @"name" }];
[map addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"permission_groups" toKeyPath:@"permissionGroups" withMapping:[PermissionGroup mapping]]];
[map addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"collaborations" toKeyPath:@"collaborations" withMapping:[ProjectCollaborator mapping]]];
}
return map;
}
我面临的问题是 collaboration.permissionGroups 关系从未建立 - 具体来说,该属性的 NSSet 是空的。我的 permissionGroupIds 属性已正确填充,与用户 (collaboration.collaborator) 的关系已正确设置。我使用了类似的策略,即一组 ID 引用其他响应中的现有对象,并且这些映射成功地工作。
我怀疑正在发生的事情是 collaborations 键首先被处理,并且所有子项都被存储,但是找不到具有提供的 ID 的相关 PermissionGroups,所以建立关系的尝试被放弃。稍后,permission_groups 键被映射并存储这些组。我有确认 PermissionGroup 对象被正确存储的单元测试。
在我看来,这个问题有两种解决方案,但我都找不到解决办法——如果可能的话,我更喜欢第一种:
- 我可以指定解析键的顺序(我已经尝试以不同的顺序添加映射)
- 我可以让 RestKit(或 CoreData?)在 CoreData 中创建一个“空”对象,稍后在填充
permission_groups键时填充该对象
这些选项是否可行,还是有更好的解决方案?
【问题讨论】:
-
您不能订购。空或存根选项是其中一个,但仅适用于您现在获取 id 和稍后获取其他对象(不同的 URL 请求)。您的所有数据都是嵌套的,因此您应该有响应描述符来创建所有对象,然后您的外键映射最后运行(确实如此)以将它们连接起来。那么 - 您目前拥有哪些响应描述符以及作为第 1 个请求的结果创建了哪些对象?
-
我已经添加了我认为你正在寻找的东西,Wain - 我最近继承了这段代码,我之前没有使用过 RestKit。我一直在为这些映射构建单元测试,并根据这些映射成功创建了我的 PermissionGroup 和 Collaboration 对象。
-
Here's a quick gist 我的单元测试。
-
JSON 是一个带有项目键字典的字典吗?我不确定,但我猜连接是在内部映射结束时运行的......
-
添加了一个答案,但不幸的是,它有点“试试看”,有趣的情况。