3

I'm developing my first iOS application that uses RestKit 0.2 and Core Data. Most of the time I have followed this great tutorial http://www.alexedge.co.uk/blog/2013/03/08/introduction-restkit-0-20/ however it doesn't fit my requirements since it describes embedded JSON objects and I need to create separate objects. Here is a simplified scenario of my app structure:

JSON response:

"application": [
    {
        "appId": "148",
        "appName": …
.
.
.
(more attributes)
    }
],
"image": [
    {
        "imgId": "308",
        "appId": "148",
        "iType": "screenshot",
        "iPath": ..
.
.
.
    },
    {
        "imgId": "307",
        "appId": "148",
        "iType": "logo",
        "iPath": …
.
.
.
    }
]

I have created a data model that contains two entities and set the relationship between them in a way that one application may have more than one image and one image may only belong to one application:

enter image description here

I have used mogenerator to create classes represented by entities.

I can successfully map the entity to Application object using the following code:

NSDictionary *parentObjectMapping = @{
                                      @"appId" : @"appId"
                                      };


// Map the Application object
RKEntityMapping *applicationMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Application class]) inManagedObjectStore:managedObjectStore];
applicationMapping.identificationAttributes = @[ @"appId" ];
[applicationMapping addAttributeMappingsFromDictionary:@{
 @"appName" : @"name",
 @"appCat" : @"category",
 @"appType" : @"type",
 @"compName" : @"companyName",
 @"compWeb" : @"companyWebsite",
 @"dLink" : @"downloadWebLink",
 @"packageName" : @"appStoreLink",
 @"osMinVer" : @"minRequirements",
 @"appCost" : @"cost",
 @"appDescription" : @"appDescription"
 }];

[applicationMapping addAttributeMappingsFromDictionary:parentObjectMapping];

 // Register our mappings with the provider
 [manager addResponseDescriptorsFromArray:@[

 [RKResponseDescriptor responseDescriptorWithMapping:applicationMapping
 pathPattern:nil
 keyPath:@"application"
 statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]
 ]];

Now I have a problem when mapping the JSON to the image object with the appropriate relationship between Image and Application. How can I add the mapping between the two Entities? Is my data model correct or I'm missing something?

2 Answers 2

5

You want to use foreign key mapping to allow RestKit to connect the objects.

You need to add an image mapping and it should have an attribute to hold the appId. Then, you need to add a connection relationship:

[imageMapping addConnectionForRelationship:@"application" connectedBy:@{ @"appId": @"appId" }];

Which tells RestKit to use the appId attribute on the image instances to connect to application instances with the corresponding appId and to save the result in the application relationship.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the reply. I have already connected Image entity with RemoteObject that way Image has appId. I also added image mapping and the connection. How can I use the foreign key to allow RestKit to connect the objects?
If you have added the addConnectionForRelationship then RestKit will make the connections automatically for you. The foreign key refers to the requirement to add the appId attribute to the image entity (because its only required to facilitate the connection).
1

I'm assuming you can't change the data structure of your "image" JSON object, so that will limit RestKit's functionality as far as automatic relational mapping goes. However, you can still set up a relationship yourself.

First, you need to add a field to your data model, appId.

Then, set up your image mapping, like this:

RKEntityMapping* imageMapping = [RKEntityMapping mappingForEntityForName:@"Image" inManagedObjectStore:objectManager.managedObjectStore];
[imageMapping addAttributeMappingsFromDictionary:@{
 @"imgId" : @"imageId",
 @"iPath" : @"clientPath",
 @"iType" : @"type",
 @"sPath" : @"serverPath",
 @"appId" : @"appId"
 }];
imageMapping.identificationAttributes = @[ @"imageId" ];
RKResponseDescriptor *imageResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:imageMapping pathPattern:nil keyPath:@"image" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:imageResponseDescriptor];

After this, your mapping should be done. To fill your local database with your objects, make this call, getObjectsAtPath:

[[RKObjectManager sharedManager] getObjectsAtPath:@"/yourWebServiceURL" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    // success block
    NSLog(@"Success!");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    //fail block
}];

This should load all of your objects into CoreData. In another place in your app, maybe even in the success block of the above call, you'll need to connect your Image objects to your Application objects. You'll need fetch requests and a for loop. Just assign every Image's "application" attribute to be the Application object which has the same appId, like this:

myImage.application = fetchedApplicationWithID;

You will then be able to look up the relationship both ways, with [myImage application] and with [myApplication images].

2 Comments

It looks like Wain has a better answer than this - I'd go with his expertise over my solution.
It seems to be working after adding the connection between Image and RemoteObject. +1 for your advices. I will accept Wain answer then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.