RestKit Add Property Mapping and Relationship Mapping - ios

Please guide me about following problem.
I have two entities with relationship as shown following image
I am using latest version of RestKit with iOS 7
Now in my appDelegate i am using following mapping for "List" Entity
NSDictionary *listObjectMapping = #{
#"listID" : #"listID",
#"listName" : #"listName",
#"listSyncStatus" : #"listSyncStatus"
};
RKEntityMapping *listEntityMapping = [RKEntityMapping mappingForEntityForName:#"List" inManagedObjectStore:managedObjectStore];
[listEntityMapping addAttributeMappingsFromDictionary:listObjectMapping];
listEntityMapping.identificationAttributes = #[ #"listID" ];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:listEntityMapping
method:RKRequestMethodGET
pathPattern:#"/api/lists"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
//Inverse mapping, to perform a POST
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[listEntityMapping inverseMapping]
objectClass:[List class]
rootKeyPath:nil
method:RKRequestMethodPOST];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"application/json"];
[objectManager addRequestDescriptor:requestDescriptor];
//Inverse mapping, to perform a PUT
requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[listEntityMapping inverseMapping]
objectClass:[List class]
rootKeyPath:nil
method:RKRequestMethodPUT];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"application/json"];
[objectManager addRequestDescriptor:requestDescriptor];
and using following mapping for my Task object
NSDictionary *taskObjectMapping = #{
#"listID" : #"listID",
#"taskID" : #"taskID",
#"taskName" : #"taskName",
#"taskCompletionStatus" : #"taskCompletionStatus",
#"taskSyncStatus" : #"taskSyncStatus"
};
RKEntityMapping *taskEntityMapping = [RKEntityMapping mappingForEntityForName:#"Task" inManagedObjectStore:managedObjectStore];
[taskEntityMapping addAttributeMappingsFromDictionary:taskObjectMapping];
taskEntityMapping.identificationAttributes = #[ #"taskID" ];
RKResponseDescriptor *taskResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:taskEntityMapping
method:RKRequestMethodGET
pathPattern:#"/api/list/:id"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:taskResponseDescriptor];
//Inverse mapping, to perform a POST
RKRequestDescriptor *taskRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[taskEntityMapping inverseMapping]
objectClass:[Task class]
rootKeyPath:nil
method:RKRequestMethodPOST];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"application/json"];
[objectManager addRequestDescriptor:taskRequestDescriptor];
//Inverse mapping, to perform a PUT
taskRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[taskEntityMapping inverseMapping]
objectClass:[Task class]
rootKeyPath:nil
method:RKRequestMethodPUT];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"application/json"];
[objectManager addRequestDescriptor:taskRequestDescriptor];
Now my question is how to add relationship mapping between these two entites ?
What would be proper way ?
If i use i use following line of code
[taskEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"list.listID"
toKeyPath:#"listID"
withMapping:listEntityMapping]];
a runtime error occurs saying "Unable to add mapping for keyPath listID, one already exists"
and if i use this
[listEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"listID"
toKeyPath:#"list.listID"
withMapping:taskEntityMapping]];
app crashes with this error the entity List is not key value coding-compliant for the key "list".'
and if i omit the above code and try to get listID from relationship
task.list.listID
it gives me "0". Can anyone tell me what exactly am i doing wrong or what should i do to accomplish above task. I can give more details on this if needed.
EDIT
but my request to all list returns following json
GET www.mydomain.com/api/lists
[
{"listID":"42","listName":"List 4","listSyncStatus":"1"},
{"listID":"41","listName":"List 3","listSyncStatus":"1"},
{"listID":"40","listName":"List 2","listSyncStatus":"1"}
]
and request to single list will return its task as follows
GET www.mydomain.com/api/list/42
[
{"taskID":"22","listID":"42","taskName":"Task 2","taskSyncStatus":"1","taskCompletionStatus":"1"},
{"taskID":"21","listID":"42","taskName":"Task 1","taskSyncStatus":"1","taskCompletionStatus":"1"}
]
i.e there is no cascading relationship in returned in json. is this wrong way or what am i missing here ?
Corrected After Accepting Answer
It turns out i was returning wrong json i.e. the returned json has no relationship in it while the iOS model has a relationship "tasks" so i edited my rest api to return correct nested json which is like below
[ { "listID" : "96",
"listName" : "List 1",
"listSyncStatus" : "1",
"tasks" : [ { "taskCompletionStatus" : "1",
"taskID" : "67",
"taskName" : "Task 2",
"taskSyncStatus" : "1"
},
{ "taskCompletionStatus" : "1",
"taskID" : "66",
"taskName" : "Task 1",
"taskSyncStatus" : "1"
}
]
},
{ "listID" : "97",
"listName" : "List 2",
"listSyncStatus" : "1",
"tasks" : [ { "taskCompletionStatus" : "1",
"taskID" : "69",
"taskName" : "Task 1",
"taskSyncStatus" : "1"
},
{ "taskCompletionStatus" : "1",
"taskID" : "68",
"taskName" : "Task 1",
"taskSyncStatus" : "1"
}
]
}
]
after returning above nested json, everything works like charm, specially this line
[listEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"tasks"
toKeyPath:#"tasks"
withMapping:taskEntityMapping]];
Hope this helps grasping relationship concepts for people like me out there.

You modal diagram shows that you have one-to-many relationship (One list has many tasks).
As far as i know, in this case you need to add relationship mapping on List entity only, no need on Task entity. Also for one-to-many relationship, you don't need to add list relationship under Task entity.
Your entities relationship should look like this
So try following
[listEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"YOUR_JSON_KEYPATH_HERE" toKeyPath:#"tasks" withMapping: taskEntityMapping]];
IMPORTANT
In above method
FromKeyPath parameter should be the name of your JSON key where the relationship starts.
toKeyPath parameter should be the relationship name that you have mentioned in Entity diagram. i.e; tasks.
withMapping should be the mapping of many entity. In you case taskEntityMapping
Hope this fix the issue.

Not sure why this is not working, but you can try to create the relationship mapping like this:
[taskEntityMapping addConnectionForRelationship:#"list" connectedBy:#{ #"listId": #"listId" }];
[listEntityMapping addConnectionForRelationship:#"tasks" connectedBy:#{ #"listId":#"listId"}];

Related

Response Descriptor for RestKit JSON Metadata

I have a JSON response that returns me a list of objects, and also a timestamp value as "MetaData". The response looks something like this --
{
"access_time": 1416467865510,
"profiles" : [
{
"user_id": "bbb91ae431b",
"email": "bob#foo.corp",
"first_name": "Bob",
"last_name": "Burroughs",
"primary_phone": "16507001212"
},
{
"user_id": "ddd8d8d8d8d",
"email": "don#foo.corp",
"first_name": "Don",
"last_name": "Darko",
"primary_phone": "14154001212"
}
]
}
My RestKit descriptor code looks something like this. And this is working well, I am getting all objects.
RKEntityMapping *contactMapping = [RKEntityMapping mappingForEntityForName:#"Contact" inManagedObjectStore: managedObjectStore];
[contactMapping addAttributeMappingsFromDictionary:#{
#"user_id" : #"userId",
#"email" : #"email",
#"first_name" : #"firstName",
#"last_name" : #"lastName",
#"primary_phone" : #"primaryPhone"
}];
contactMapping.identificationAttributes = #[#"userId"];
RKResponseDescriptor *contactResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:contactMapping method:RKRequestMethodAny pathPattern:nil keyPath:#"profiles" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
The above thing works well for me.
However, I wanted to have access to the access_time field above too. How do I get access to that? I am thinking of storing that value in NSUserDefaults for later use since it is not a field that is a part of the User/Contact object. How do I do it?
try this:
[contactMapping addAttributeMappingsFromDictionary:#{
#"user_id" : #"userId",
#"email" : #"email",
#"first_name" : #"firstName",
#"last_name" : #"lastName",
#"primary_phone" : #"primaryPhone",
#"#parent.access_time" : #"accessTime",
}];
You can read more here
You could create a relationship between the parent JSON object (that contains "access_time") and the child "profiles" objects with RKRelationshipMapping.
Then instead of having your response descriptor directly accessing the keyPath:#"profiles", you can set it to keyPath:nil and access the whole JSON object including access_time and associated profiles.
You would also need to ensure you had a corresponding Entity and Relationships (in the datamodel) for the parent JSON object (you can call it whatever you like). Then back in the file with the RestKit mappings add the relationships to the parent mapping object with addPropertyMappingsFromArray:.
Then once the request is returned you can iterate through the associated profile objects of the parent JSON (assuming you have XCode create the associated NSManagedObject subclasses) with a simple:
// allObjects returns an NSArray representation of the NSSet
NSArray *profiles = [[parentObject valueForKeyPath:#"profiles"] allObjects];
Hopefully this helps.

Map only on element of a one to many relationships

I'm stuck with the following problem. I have a relationships one_to_many between a Event and Comment. One Event can have many Comment but a Comment has belongs_to only one Event.
Until here, everything is fine. Now, when I'm adding a comment, I would like to map only this new comment. That means I'm using my relationship from Comment to Moment.
I have some troubles with the mapping that I'm not able to solve. My error is at the end of this post after all the description.
I'm receiving this JSON:
"comment": {
"id": 17,
"commentable_id": 12,
"commentable_type": "Moment",
"content": "That's it ! ",
"created_at": "2014-06-20T18:17:42Z",
"updated_at": "2014-06-20T18:17:42Z",
"user_id": 1,
"creator": {
"id": 1,
"email": "test#test.com",
"firstname": "Bobby",
"lastname": "Stouket",
"gender": 0,
"created_at": "2014-04-06T17:48:11Z",
"updated_at": "2014-06-20T18:17:26Z"
}
}
Here is my comment mapping:
RKEntityMapping *commentMapping = [RKEntityMapping mappingForEntityForName:#"Comment" inManagedObjectStore:store];
commentMapping.identificationAttributes = #[ #"commentId"];
[commentMapping addAttributeMappingsFromDictionary:#{
#"id" : #"commentId",
#"updated_at": #"updatedAt",
#"created_at": #"createdAt",
#"user_id": #"userId",
#"commentable_id": #"commentableId",
#"commentable_type": #"commentableType",
#"content": #"content"
}];
RKEntityMapping *userCreatorMapping = [APICallUser RKGetUserMappingOnlyWithAvatarForManagedObjectStore:store];
[commentMapping addConnectionForRelationship:#"creator" connectedBy:#{#"userId": #"userId"}];
[commentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"creator"
toKeyPath:#"creator"
withMapping:userCreatorMapping]];
Here is my code for my moment mapping (with the association with comments which is working) :
RKEntityMapping *momentMapping = [RKEntityMapping mappingForEntityForName:#"Moment" inManagedObjectStore:store];
momentMapping.identificationAttributes = #[ #"momentId"];
[momentMapping addAttributeMappingsFromDictionary:#{
#"id" : #"momentId",
#"creator.id" : #"creatorId",
#"created_at" : #"createdAt",
#"updated_at" : #"updatedAt"
}];
RKEntityMapping *commentMapping = [APICallComment RKGetCommentMappingForManagedObjectStore:store];
[commentMapping addConnectionForRelationship:#"moment" connectedBy:#{#"commentableId":#"momentId"}];
[momentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"comments"
toKeyPath:#"comments"
withMapping:commentMapping]];
There is one more thing to know is that a comment can be on a moment or on a photo. According to my JSON, I don't think I need an RKDynamicMapping but I'm not sure.
Here is the code when I'm using my mapping. The request is send successfully and I receive the JSON written before.
KEntityMapping *commentMapping = [APICallComment RKGetCommentMappingForManagedObjectStore:self.appDelegate.managedObjectStore];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:commentMapping
method:RKRequestMethodPOST
pathPattern:APICallCommentCreateCommentsRouteName
keyPath:#"comment"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[session.objectManager addResponseDescriptor:responseDescriptor];
//session.objectManager.requestSerializationMIMEType=RKMIMETypeJSON;
Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched." UserInfo=0xb8a9150 {DetailedErrors=(), NSLocalizedFailureReason=The mapping operation was unable to find any nested object representations at the key paths searched: comments, device, devices
The representation inputted to the mapper was found to contain nested object representations at the following key paths: comment
This likely indicates that you have misconfigured the key paths for your mappings., NSLocalizedDescription=No mappable object representations were found at the key paths searched., keyPath=null}
Edit:
Here is the result of the code line session.objectManager.requestDescriptor. It's really weird. I can see only 1 object in the NSArray. When I print it I can read:
Printing description of $1:
<__NSArrayI 0xbd61010>(
<RKRequestDescriptor: 0xbd12bb0 method=(POST) objectClass=BasicLocation rootKeyPath=position : <RKObjectMapping:0xbd40b70 objectClass=NSMutableDictionary propertyMappings=(
"<RKAttributeMapping: 0xbd545d0 latitude => lat>",
"<RKAttributeMapping: 0xbd58430 longitude => lng>"
)>>
)
Nowhere I've written that positionshould be the rootKeyPath and my other attributes are not here (content, commentableType, userId, createdAt, updatedAt, commentId).
Thank you for your help.
You create:
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:commentMapping
method:RKRequestMethodPOST
pathPattern:APICallCommentCreateCommentsRouteName
keyPath:#"comment"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
but you can't ever add it to the object manager, because it only understands comments, device, devices.
That would seem to be your main issue.
You wouldn't usually do this:
[commentMapping addConnectionForRelationship:#"creator" connectedBy:#{#"userId": #"userId"}];
[commentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"creator"
toKeyPath:#"creator"
withMapping:userCreatorMapping]];
because you are supplying 2 different mappings for exactly the same content and relationship where you only need one because the user information is nested inside the comment information. So, you can remove the foreign key mapping (addConnectionForRelationship:).
The mapping was good but the mistake comes from here:
[RKResponseDescriptor responseDescriptorWithMapping:commentMapping
method:RKRequestMethodGET
pathPattern:HERE
keyPath:#"comment"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
I didn't write the path pattern. This variable changed and everything works perfectly.

Wrong RKResponseDescriptor - nested object found but not mappable

I have the following entity mapping and descriptor:
RKEntityMapping *responseUserMapping = [APICallUser RKGetUserMappingForManagedObjectStore:self.appDelegate.managedObjectStore];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseUserMapping
[session.objectManager addResponseDescriptor:responseDescriptor];
method:RKRequestMethodPOST
pathPattern:APICallUserCreatePattern
keyPath:#"user"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
Here is the description of the method RKGetUserMappingForManagedObjectStore
+ (RKEntityMapping *) RKGetUserMappingForManagedObjectStore:(RKManagedObjectStore *) store{
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:#"User" inManagedObjectStore:store];
userMapping.identificationAttributes = #[ #"userId" ];
[userMapping addAttributeMappingsFromDictionary:#{
#"id" : #"userId",
#"email" : #"email",
#"firstname" : #"firstName",
#"lastname" : #"lastName",
#"gender" : #"gender",
#"time_zone" : #"timeZone",
#"created_at" : #"createdAt",
#"nickname" : #"pseudo",
#"facebook_id" : #"facebookId",
#"facebook_link_asked_at" : #"lastQueryForFacebookLinkDate",
#"birthday" : #"birthDate",
#"city" : #"city",
#"country" : #"country",
#"sign_in_count" : #"signInCount",
#"facebook_token" : #"facebookToken",
#"facebook_token_expires_at" : #"facebookExpiration",
#"avatar.id" : #"avatarPhotoId"
}];
RKEntityMapping *photoMapping = [APICallPhoto RKGetPhotoMappingForManagedObjectStore:store];
photoMapping.setNilForMissingRelationships = YES;
[userMapping addConnectionForRelationship:#"avatarPhoto" connectedBy:#{#"avatarPhotoId" : #"photoId"}];
//[photoMapping addConnectionForRelationship:#"avatarUsers" connectedBy:#{ #"photoId": #"avatarPhotoId" }];
[userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"avatar" toKeyPath:#"avatarPhoto" withMapping:photoMapping]];
return userMapping;
}
And the code for the method RKGetPhotoMappingForManagedObjectStore
+ (RKEntityMapping *) RKGetPhotoMappingForManagedObjectStore:(RKManagedObjectStore *) store{
RKEntityMapping *photoMapping = [RKEntityMapping mappingForEntityForName:#"Photo" inManagedObjectStore:store];
photoMapping.identificationAttributes = #[ #"photoId" ];
[photoMapping addAttributeMappingsFromDictionary:#{
#"id" : #"photoId",
#"moment_id" : #"momentId",
#"user_id" : #"userId",
#"title" : #"title",
#"description" : #"photoDescription",
#"file.thumb_url" : #"thumbnailDistURL",
#"file.mini_url" : #"miniDistURL",
#"file.little_url" : #"littleDistURL",
#"file.medium_url" : #"mediumDistURL",
#"file.public_url" : #"originalDistURL"
}];
/*RKEntityMapping *momentMapping = [APICallMoment RKGetMomentMappingForManagedObjectStore:store];
[momentMapping addConnectionForRelationship:#"photos" connectedBy:#{ #"momentId": #"momentId" }];
[photoMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"moment" toKeyPath:#"moment" withMapping:momentMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:photoMapping method:RKRequestMethodAny pathPattern:nil keyPath:#"photos" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
*/
return photoMapping;
}
This is my json that my app received:
{
"user": {
"id": 38,
"email": "test#test.com",
"firstname": "bob",
"lastname": "tonny",
"gender": 0,
"created_at": "2014-04-19T11:00:55Z",
"updated_at": "2014-04-19T11:00:55Z",
"nickname": "bobby",
"facebook_id": null,
"birthday": "1990-02-14",
"city": "",
"country": "",
"facebook_token": null,
"facebook_token_expires_at": null,
"time_zone": "Europe/Paris",
"facebook_link_asked_at": null,
"sign_in_count": 0,
"confirmed": false,
"badge": {
"permanent": 0,
"contextual": 0
},
"avatar": null
}
}
You can see that there is no relation with device or devices here. But I have the exact following error:
error=Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched." UserInfo=0xd0c1770 {DetailedErrors=(
), NSLocalizedFailureReason=The mapping operation was unable to find any nested object representations at the key paths searched: device, devices
The representation inputted to the mapper was found to contain nested object representations at the following key paths: user
This likely indicates that you have misconfigured the key paths for your mappings., NSLocalizedDescription=No mappable object representations were found at the key paths searched., keyPath=null}
I'm currently not able to find where the problem comes from.
The only relation between User and Device is set on the .xcdatamodelId like you can see on the following pictures:
relationship for User
relationship for Device
I took a lot at the descriptors: session.objectManager.responseDescriptors. There are several descriptors but none about any devices.
If anyone can just see where I'm missing something, I would really like to know it.
Thank you in advance.
I found the solution. It was not obvious at all. After adding my descriptor to the objectManager, I did that:
session.objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
That solved completely my problem. I don't know why it's important to precise here because I already set this property a long time ago on my code..
Edit: It WAS working ! I didn't touch anything but now it's not working.
Edit 2: I finally got it :
I was using
`[session.objectManager addResponseDescriptor:responseDescriptor];
session.objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[[RKObjectManager sharedManager] managedObjectRequestOperationWithRequest:request managedObjectContext:session.objectManager.managedObjectStore.mainQueueManagedObjectContext success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)`
I changed [RKObjectManager sharedManager] by my variable session.objectManager and everything work fine !
I hope it will help someone else.

RestKit crashing at RKEntityMapping line

I am new to Objective-C and very stuck with RestKit. I am trying to create a very simple UITableView with data from JSON on my web server and I have been stuck for a while.
This is my simple JSON:
{
"restaurants": [
{
"id": "27",
"franchise_name": "Franchise 1",
"branch_name": "Branch 1",
"branch_phone": "0200 111 0000",
"cuisine": "Salad",
"cooking_time": "15",
"is_open": 1
},
{
"id": "97",
"franchise_name": "Franchise 2",
"branch_name": "Branch 2",
"branch_phone": "0207 222 0000",
"cuisine": "Healthy",
"cooking_time": "10",
"is_open": 1
}
]
}
This is my Core Data model:
Entities: Restaurant
Attributes: branchName -> String
franchiseName -> String
id -> integer 16
readyTime-> integer 16
I have the following code in my view controller. In viewDidLoad, RKEntityMapping causes an exception:
RKManagedObjectStore *managedObjectStore = [RKManagedObjectStore defaultStore];
RKEntityMapping *entityMapping = [RKEntityMapping mappingForEntityForName:#"Restaurant" inManagedObjectStore:managedObjectStore]; //THIS LINE CAUSES THE CRASH
[entityMapping addAttributeMappingsFromDictionary:#{
#"id": #"id",
#"cooking_time": #"readyTime",
#"branch_name": #"branchName",
#"franchise_name": #"franchiseName"}];
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:#"/api/restaurants" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; //I GET AN ISSUE HERE AS WELL INVOLVING responseDescriptorWithMapping BEING DEPRECIATED.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http//mywebserver.com/api/resturants"]];
RKManagedObjectRequestOperation *managedObjectRequestOperation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[ responseDescriptor ]];
managedObjectRequestOperation.managedObjectContext = self.managedObjectContext;
[[NSOperationQueue currentQueue] addOperation:managedObjectRequestOperation];
There are several error messages none of which I really get:
NSAssert(objectClass, #"Cannot initialize an entity mapping for an entity with a nil managed object class: Got nil class for managed object class name '%#'. Maybe you forgot to add the class files to your target?", [entity managedObjectClassName]);
In the console:
*** Assertion failure in -[RKEntityMapping initWithEntity:],
responseDescriptorWithMapping is deprecated, it now has an extra method parameter. This is just a warning - you should update but you don't have to.
If the crash happens when you try to use the managedObjectStore for the first time it would suggest that you haven't properly / fully configured your Core Data stack (or that your entity name / class name is wrong). Check this doc for a simple overview of what setup is required. If you want to use an object manager, check this doc.

RestKit 0.20 NSCFConstantString valueForUndefinedKey error while mapping relationship

So I'm trying to map JSON with objects looking like this
{
"item_id": "0",
"product_id": "217",
"color_id": "55",
"size_id": "37",
"images": [
{
"image_url": "http://www.foo.com/bar.jpg"
}
]
},
I map it directly to Core Data entity 'Item'. This entity has one-to-many relationship to entities 'Pictures' called 'images'. Entity 'Picture' has one NSString attribute 'image_url'. Here are my mappings:
- (void) setupPicturesMapping
{
picturesMapping = [RKEntityMapping mappingForEntityForName:#"Pictures" inManagedObjectStore:self.objectManager.managedObjectStore];
picturesMapping.identificationAttributes = #[#"image_url"] ;
[picturesMapping addAttributeMappingsFromArray:#[#"image_url"]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:picturesMapping
pathPattern:#"get_pictures"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self.objectManager addResponseDescriptor:responseDescriptor];
}
- (void) setupItemsMapping
{
itemsMapping = [RKEntityMapping mappingForEntityForName:#"Item" inManagedObjectStore:self.objectManager.managedObjectStore];
itemsMapping.identificationAttributes = #[#"item_id"] ;
[itemsMapping addAttributeMappingsFromArray:#[#"item_id", #"product_id", #"color_id", #"size_id"]];
[itemsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"images" toKeyPath:#"images" withMapping:picturesMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:itemsMapping
pathPattern:#"get_items"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self.objectManager addResponseDescriptor:responseDescriptor];
}
When I try to load items I get an error: "Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFConstantString 0x26f72b4> valueForUndefinedKey:]: this class is not key value coding-compliant for the key image_url.'".
What's the problem?
UPDATE: Sorry, posted wrong code for the first time
I think you are passing wrong entity name here-
picturesMapping = [RKEntityMapping mappingForEntityForName:#"Pictures" inManagedObjectStore:self.objectManager.managedObjectStore];
Pass "Picture" instead of "Pictures" like-
picturesMapping = [RKEntityMapping mappingForEntityForName:#"Picture" inManagedObjectStore:self.objectManager.managedObjectStore];

Resources