如何处理对尚不存在的对象的 ID 引用的 RestKit 嵌套数组?

Posted

技术标签:

【中文标题】如何处理对尚不存在的对象的 ID 引用的 RestKit 嵌套数组?【英文标题】:How to handle RestKit nested array of ID references to objects that don't exist yet? 【发布时间】: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 是一个带有项目键字典的字典吗?我不确定,但我猜连接是在内部映射结束时运行的...... 添加了一个答案,但不幸的是,它有点“试试看”,有趣的情况。 【参考方案1】:

理想情况下,RK 会从所有映射中获取所有连接映射来处理并在最后运行它们,但我没有检查是否是这种情况。

如果不是,而且从您的情况来看,您需要确保所有对象都已创建,然后再尝试连接它们。

这是我在您的确切配置中没有尝试过的东西,但我会尝试创建 2 个其他响应描述符并将它们放在您当前的数组之前的数组中。每个都将使用内部映射(组然后协作)并使用键路径钻入相关的数据数组。

主要问题是我没有检查请求操作(或更确切地说它将启动的映射操作)是否按顺序使用响应描述符数组。如果是这样,那么所有内部对象都将被创建,然后项目将被创建并连接到它们,然后它们将相互连接。

【讨论】:

所以,我运行的测试只是映射测试,不使用描述符(据我所知)。也就是说,我进行了一些其他模拟 API 响应的测试,我玩过这些测试并看到了相同的结果。我尝试了这个解决方案(在“项目”之前添加“project.permission_groups”键路径的描述符),不幸的是仍然看到相同的结果 - 一组空的关系。 [RKResponseDescriptor responseDescriptorWithMapping:[PermissionGroup mapping] method:RKRequestMethodGET pathPattern:@"projects/:serverId" keyPath:@"project.permission_groups" statusCodes:successCodes] 下一步是打开跟踪日志记录并查看有关查找要连接的对象的内容以及尝试的顺序 所以,嗯。哎呀。看来我从来没有映射权限组的id 属性,这意味着永远没有匹配的对象来创建关系!不过,打开日志记录帮助我追踪到了这一点——谢谢你的建议,它真的应该是我的第一个停靠港。您理解关系是在 映射似乎正确之后创建的;我的模拟 API 响应不需要额外的描述符,这在我的映射单元测试中也可以正常工作。 ...好悲伤我在另一个测试中测试了 id 映射,当我删除这个修复时它也失败了,不知道我是怎么错过的。非常感谢您的帮助 Wain,很抱歉将您的时间浪费在原来实际上并不是一个有趣的问题上。

以上是关于如何处理对尚不存在的对象的 ID 引用的 RestKit 嵌套数组?的主要内容,如果未能解决你的问题,请参考以下文章

WPF 如何处理对空对象属性的绑定?

c#:如何处理对对象进行深度拷贝

如何处理对 UITableView 的非单元格区域的点击

如何处理对客户端反应应用程序的外部重定向?

postgres 如何处理对某些列具有假值的视图的查询?

如何处理对 RecyclerView 列表项内部视图的点击。使用数据绑定和 kotlin