通过一组ID在RestKit映射关系不工作(Mapping relationships in Res

2019-07-02 12:55发布

我想CoreData对象通过RestKit,保持两者之间的关系以映射用户和组。

为用户的JSON是一样的东西

{"users":
  [{"fullname": "John Doe", "_id": "1"}
   ...
  ]
}

而各组的JSON是一样的东西

{"groups":
  [{"name": "John's group", "_id": "a",
    "members": ["1", "2"]
   ...
  ]
}

我也有相应的核心数据对象, UserGroup ,与组和用户之间有一个对多的关系的映射。 在关系属性Group被称为members和一个单独NSArray称为memberIDs保存所有成员用户的字符串ID的数组。

我想在RestKit做到的是加载这些对象,并有映射我的关系。 加载用户的代码是直线前进标准的东西,以及加载组的代码是一样的东西

RKObjectManager* objectManager = [RKObjectManager sharedManager];
RKManagedObjectMapping* groupMapping = [RKManagedObjectMapping mappingForClass:[Group class] inManagedObjectStore:objectManager.objectStore];
groupMapping.primaryKeyAttribute = @"identifier";
[groupMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping mapKeyPath:@"name" toAttribute:@"name"];
[groupMapping mapKeyPath:@"members" toAttribute:@"memberIDs"];
[objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups"];

// Create an empty user mapping to handle the relationship mapping
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];

[groupMapping hasMany:@"members" withMapping:userMapping];
[groupMapping connectRelationship:@"members" withObjectForPrimaryKeyAttribute:@"memberIDs"];

RKObjectRouter* router = objectManager.router;

[router routeClass:[Group class] toResourcePath:@"/rest/groups/:identifier"];
[router routeClass:[Group class] toResourcePath:@"/rest/groups/" forMethod:RKRequestMethodPOST];
// Assume url is properly defined to point to the right path...
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader) {}];

当我运行这段代码,我得到以下警告吐几次(似乎是每个关系的两倍左右):

2012-10-24 08:55:10.170 Test[35023:18503] W restkit.core_data.cache:RKEntityByAttributeCache.m:205 Unable to add object with nil value for attribute 'identifier': <User: 0x86f7fc0> (entity: User; id: 0x8652400 <x-coredata:///User/t01A9EDBD-A523-4806-AFC2-9B06873D764E531> ; data: {
    fullname = nil;
    identifier = nil;
})

奇怪的是,这种关系被设置正确(甚至看着SQLite数据库,一切看起来不错有),但我不开心的东西在RestKit代码显然会错,它似乎有事情做与伪造用户映射我在上面的代码中创建(它是空的,因为没有什么ID的阵列中的映射)。

我试过的替代品,例如,当我添加了关键路径映射:

[userMapping mapKeyPath:@"" toAttribute:@"identifier"];

它抱怨,显然是因为关键路径为空

2012-10-24 09:24:11.735 Test[35399:14003] !! Uncaught exception !!
[<__NSCFString 0xa57f460> valueForUndefinedKey:]: this class is not key value coding-compliant for the key .

如果我尝试使用真正的User映射

[groupMapping hasMany:@"members" withMapping:[[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"users"]];

我得到以下错误

2012-10-24 09:52:49.973 Test[35799:18403] !! Uncaught exception !!
[<__NSCFString 0xa56e9a0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _id.
2012-10-24 09:52:49.973 Test[35799:18403] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0xa56e9a0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _id.'

好像RestKit正试图将自己映射ID字符串数组memberIDs在User对象,这没有任何意义。 我已经看到例子,其中关系阵列是与键字典列表(例如称为id )与基准ID到另一个物体,例如:

{"groups":
  [{"name": "John's group", "_id": "a",
    "members": [
      {"_id": "1"},
      {"_id": "2"}
     ]
   ...
  ]
}

但我不想改变我的JSON以这种方式(此外,我希望RestKit具有足够的灵活性来支持其他的方式。)

有谁知道做这种映射关系的RestKit是正确的方法是什么?

更新

我结束了修改REST接口发送包含用户对象ID(就像上面的最后一个例子)的词典列表,并得到了工作。 还没有完全满意的设置,但现在的代码如下所示

RKObjectManager* objectManager = [RKObjectManager sharedManager];
RKManagedObjectMapping* groupMapping = [RKManagedObjectMapping mappingForClass:[Group class] inManagedObjectStore:objectManager.objectStore];
groupMapping.primaryKeyAttribute = @"identifier";
[groupMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping mapKeyPath:@"name" toAttribute:@"name"];
[groupMapping mapKeyPath:@"members._id" toAttribute:@"memberIDs"];
[objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups"];

// Create an empty user mapping to handle the relationship mapping
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];
userMapping.primaryKeyAttribute = @"identifier";
[userMapping mapKeyPath:@"_id" toAttribute:@"identifier"];

[groupMapping hasMany:@"members" withMapping:userMapping];
[groupMapping connectRelationship:@"members" withObjectForPrimaryKeyAttribute:@"memberIDs"];

RKObjectRouter* router = objectManager.router;

[router routeClass:[Group class] toResourcePath:@"/rest/groups/:identifier"];
[router routeClass:[Group class] toResourcePath:@"/rest/groups/" forMethod:RKRequestMethodPOST];
// Assume url is properly defined to point to the right path...
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader) {}];

以防万一,这可以帮助其他人在类似的情况。 有可能仍然会有一些问题,我采取的方法,但到目前为止好(甚至处理乱序负荷,这是很好的) - 还是愿意爱从别人听到,如果有一个答案,我原来的问题。

Answer 1:

找到了一种方法,使这项工作,并且也认识到,在我的问题的更新方法只应该用于嵌套的对象,而不是引用的对象。 此线程让我在正确的轨道上: https://groups.google.com/forum/#!msg/restkit/swB1Akv2lT​​E/mnP2OMSqElwJ (值得一读,如果你正在处理中RestKit关系)

假设组JSON看起来还是像原来的JSON:

{"groups":
  [{"name": "John's group", "_id": "a",
    "members": ["1", "2"]
   ...
  ]
}

此外,假设用户映射到的keyPath users (即在类似[objectManager.mappingProvider setMapping:userMapping forKeyPath:@"users"];映射关系的正确方法是这样的:

RKObjectManager* objectManager = [RKObjectManager sharedManager];
RKManagedObjectMapping* groupMapping = [RKManagedObjectMapping mappingForClass:[Group class] inManagedObjectStore:objectManager.objectStore];
groupMapping.primaryKeyAttribute = @"identifier";
[groupMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping mapKeyPath:@"name" toAttribute:@"name"];
[groupMapping mapKeyPath:@"members" toAttribute:@"memberIDs"];
[objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups"];

[groupMapping mapKeyPath:@"users" toRelationship:@"members" withMapping:[[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"users"] serialize:NO];
[groupMapping connectRelationship:@"members" withObjectForPrimaryKeyAttribute:@"memberIDs"];

RKObjectRouter* router = objectManager.router;
[router routeClass:[Group class] toResourcePath:@"/rest/groups/:identifier"];
[router routeClass:[Group class] toResourcePath:@"/rest/groups/" forMethod:RKRequestMethodPOST];
// Assume url is properly defined to point to the right path...
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader) {}];

当我有这种方法做过这样的尝试,即困惑我的事情是这条线

[groupMapping mapKeyPath:@"users" toRelationship:@"members" withMapping:[[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"users"] serialize:NO];

其中,第一键路径被参照密钥路径映射用于被引用的对象( users在这种情况下),而不是内的关系的关键路径group对象被映射(这将有members在这种情况下)。

随着这一变化,所有的关系按预期工作,我很高兴。



文章来源: Mapping relationships in RestKit through an array of IDs doesn't work
标签: ios restkit