I will try to be as descriptive as possible with this issue...
我将尽量用描述性的语言来描述这个问题。
Scenario
场景
Let's say i have a NSManagedObject 'User'
假设我有一个NSManagedObject 'User'
@class Premise;
@interface User : NSManagedObject
@property (nonatomic, retain) NSNumber * identifier;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *premises;
@end
@interface User (CoreDataGeneratedAccessors)
- (void)addPremisesObject:(Premise *)value;
- (void)removePremisesObject:(Premise *)value;
- (void)addPremises:(NSSet *)values;
- (void)removePremises:(NSSet *)values;
@end
And i also have a NSManagedObject 'Premise'
我还有NSManagedObject "前提"
@class User;
@interface Premise : NSManagedObject
@property (nonatomic, retain) NSNumber * identifier;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) User *user;
@end
Based on it, i am creating a relationship route to map a JSON array of 'Premise' to the 'premises' attribute on the 'User' object.
基于此,我创建了一个关系路由,将“前提”的JSON数组映射到“用户”对象的“前提”属性。
Here's the route:
路线:
let getPremisesRoute = RKRoute(relationshipName: "premises",
objectClass: User.self,
pathPattern: "user/:identifier/premises",
method: .GET)
Here's the JSON response (/user/1/premises):
这里是JSON响应(/user/1/premises):
[
{
"id": 35,
"name": "Icaraí"
},
{
"id": 32,
"name": "Remanso"
}
]
Here's the response descriptor:
这是响应描述符:
let getPremisesResponseDescriptor = RKResponseDescriptor(mapping: premiseMapping, method: .GET, pathPattern: "user/:identifier/premises", keyPath: nil, statusCodes: RKStatusCodeIndexSetForClass(.Successful))
And here are the respective mappings of 'User' and 'Premise'
这是用户和前提的映射
let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: moc)
userMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])
userMapping.identificationAttributes = ["identifier"]
userMapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: nil, toKeyPath: "premises", withMapping: premiseMapping))
let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])
premiseMapping.identificationAttributes = ["identifier"]
Now to my problem
现在我的问题
Apparently, Restkit is getting a little bit confused during the mapping process. Here's the database after the request:
显然,在映射过程中,Restkit有点混乱。以下是请求后的数据库:
User Table:
用户表:
Premise Table:
前提下表:
Note the the relationship is not being created between the entities.
注意,实体之间没有创建关系。
Now, if I change the response descriptor's mapping from premise to user mapping, the database changes to this:
现在,如果我将响应描述符的映射从前提更改为用户映射,那么数据库将更改为:
Users Table:
用户表:
Premise Table:
前提下表:
I'm really confused on what's going on and I've tried a lot of solutions with no success.
我对发生了什么感到很困惑,我尝试了很多解决方案,但都没有成功。
Is the JSON response out of pattern or am I doing something wrong? The JSON response seems to be on a common pattern, with a nil key path.
JSON响应没有模式,还是我做错了什么?JSON响应似乎处于一个通用模式,具有nil键路径。
2 个解决方案
#1
1
You're approaching the mapping incorrectly, or at least your mappings are wrong for what you're doing. Consider that the response is a user, but only the premises for a user, instead of considering it as a simple list of premises as you are now. Then you map to a user and insert the premises. Something like:
你对映射的处理是错误的,或者至少你的映射是错误的。考虑响应是一个用户,但只是用户的前提,而不是像现在这样把它看作一个简单的前提列表。然后映射到用户并插入前提。喜欢的东西:
RKResponseDescriptor(mapping: userMapping, method: .GET, pathPattern: "user/:identifier/premises", keyPath: nil, statusCodes: RKStatusCodeIndexSetForClass(.Successful))
And here are the respective mappings of 'User' and 'Premise'
这是用户和前提的映射
let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: moc)
userMapping.addAttributeMappingsFromDictionary(["@metadata.routing.parameters.idEntities":"identifier"])
userMapping.identificationAttributes = ["identifier"]
userMapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: nil, toKeyPath: "premises", withMapping: premiseMapping))
let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])
premiseMapping.identificationAttributes = ["identifier"]
You don't have a user name in the response so you can't map it, and the user id is actually in the request so you need to use metadata to extract it.
响应中没有用户名,因此无法映射它,而用户id实际上位于请求中,因此需要使用元数据来提取它。
#2
1
Ok, I found a possible solution based on @Wain's solution using foreign keys.
好的,我找到了一个基于@Wain使用外键的解决方案。
I added a new property 'userID' to the 'Premise' entity and mapped it to the identifier on the URL using metadata
我向“前提”实体添加了一个新属性“userID”,并使用元数据将其映射到URL的标识符。
let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name", "@metadata.routing.parameters.identifier":"userID"])
Then I added a relationship connection to the 'premiseMapping'
然后我添加了一段关系到“前错”
premiseMapping.addConnectionForRelationship("user", connectedBy: ["userID":"identifier"])
If anyone has a more elegant solution please share with us.
如果有人有更优雅的解决方案,请与我们分享。
#1
1
You're approaching the mapping incorrectly, or at least your mappings are wrong for what you're doing. Consider that the response is a user, but only the premises for a user, instead of considering it as a simple list of premises as you are now. Then you map to a user and insert the premises. Something like:
你对映射的处理是错误的,或者至少你的映射是错误的。考虑响应是一个用户,但只是用户的前提,而不是像现在这样把它看作一个简单的前提列表。然后映射到用户并插入前提。喜欢的东西:
RKResponseDescriptor(mapping: userMapping, method: .GET, pathPattern: "user/:identifier/premises", keyPath: nil, statusCodes: RKStatusCodeIndexSetForClass(.Successful))
And here are the respective mappings of 'User' and 'Premise'
这是用户和前提的映射
let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: moc)
userMapping.addAttributeMappingsFromDictionary(["@metadata.routing.parameters.idEntities":"identifier"])
userMapping.identificationAttributes = ["identifier"]
userMapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: nil, toKeyPath: "premises", withMapping: premiseMapping))
let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])
premiseMapping.identificationAttributes = ["identifier"]
You don't have a user name in the response so you can't map it, and the user id is actually in the request so you need to use metadata to extract it.
响应中没有用户名,因此无法映射它,而用户id实际上位于请求中,因此需要使用元数据来提取它。
#2
1
Ok, I found a possible solution based on @Wain's solution using foreign keys.
好的,我找到了一个基于@Wain使用外键的解决方案。
I added a new property 'userID' to the 'Premise' entity and mapped it to the identifier on the URL using metadata
我向“前提”实体添加了一个新属性“userID”,并使用元数据将其映射到URL的标识符。
let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name", "@metadata.routing.parameters.identifier":"userID"])
Then I added a relationship connection to the 'premiseMapping'
然后我添加了一段关系到“前错”
premiseMapping.addConnectionForRelationship("user", connectedBy: ["userID":"identifier"])
If anyone has a more elegant solution please share with us.
如果有人有更优雅的解决方案,请与我们分享。