8

I'm using RestKit for a project and i noticed that there is no longer a method in the class that you can control all mappings in (elementToPropertyMappings), i therefore wondered where the best place to put the new code was, currently i'm doing it in my view controller, but i'll be using most of the same mappings in other areas of my code so is there a more efficient place to put it:

The code i am referring to is:

RKObjectMapping* userMapping = [RKObjectMapping mappingForClass:[User class]];
[userMapping mapKeyPath:@"id" toAttribute:@"identifier"];
[userMapping mapKeyPath:@"forename" toAttribute:@"forename"];
[userMapping mapKeyPath:@"surname" toAttribute:@"surname"];
[userMapping mapKeyPath:@"email" toAttribute:@"email"];
[userMapping mapKeyPath:@"twitter_username" toAttribute:@"twitterUsername"];
[userMapping mapKeyPath:@"created" toAttribute:@"created"];
[userMapping mapKeyPath:@"use_gravatar" toAttribute:@"useGravatar"];
[userMapping mapKeyPath:@"avatar_url" toAttribute:@"avatarURL"];
[userMapping mapKeyPath:@"gender" toAttribute:@"gender"];
[[RKObjectManager sharedManager].mappingProvider setMapping:userMapping forKeyPath:@"user"];

It would be great if this could be in a method on the User class that i can then call to setup these mappings etc.

Many Thanks

3 Answers3

9

There are a few good ways to organize your mappings currently recommended:

  1. Put all of your mappings into your app delegate and configure them at app initialization. This keeps them out of the controllers and is useful if you have a small number of mappings.
  2. Subclass the RKObjectMappingProvider and build all of your mappings in the init method of your subclass, then instantiate and assign your mapping provider instance to the object manager.
  3. Add a category to RKObjectMappingProvider with a method like 'defineMappings'. Then import the header into your app delegate and invoke it via [mappingProvider defineMappings] after you initialize RestKit.

The problem with defining mappings on a class method is that when you have relationships, you can wind up with circular dependencies as there's no ivars available to store the instances. We may be able to do something with blocks to help alleviate this problem, but no such work has been done yet.

Blake Watters
  • 6,607
  • 1
  • 43
  • 33
  • 1
    In the past I've just created a RestKitManager and a MappingsManager object to move the setup out of my app delegate. The mappings manager keeps a reference to each of the mappings I've defined and it provides a single point-of-entry to the RestKitManager to initiate and setup the mappings, so that neither the RestKitManager, nor the AppDelegate need to know any details about the number of entities involved. *HOWEVER* subclassing the mapping provider seems like a more elegant approach. I had not considered that before. – Greg Combs Sep 03 '11 at 16:07
  • not wanting to hijack this question I asked a very closely related question here: http://stackoverflow.com/questions/7399095/where-to-put-object-mappings-in-restkit – Glenn Sep 13 '11 at 08:51
3

I think the domain model should be the only one who should know about the mapping. Here is how I map some flickr json:

I call the mappings when you need them (Can be in AppDelegate or where ever you want)

// Setup our object mappings
RKObjectMapping *photoMapping = [Photo mapWithMapping:nil];
RKObjectMapping *photosMapping = [Photos mapWithMapping:photoMapping];

And this is one of my domain objects: It contains the classMethod doing the mapping.

#import "Photos.h"
@implementation Photos

+ (RKObjectMapping*)mapWithMapping: (RKObjectMapping*)aMapping
{
    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[self class] inManagedObjectStore:objectManager.objectStore];

    [mapping mapKeyPathsToAttributes:
         @"page", @"page",
         @"pages", @"pages",
         @"perpage", @"perpage",
         @"stat", @"stat",
         @"total", @"total",
     nil];

    if (aMapping) {
        [mapping mapRelationship:@"photo" withMapping:aMapping];
    }

    return mapping;
}

@end
Tycho Pandelaar
  • 7,367
  • 8
  • 44
  • 70
1

I typically create a private method in my App Delegate that I call during app setup which sets up the RKObjectManager and then constructs all the mappings I use throughout the app. I believe the RestKit sample projects use this same pattern, so definitely check those out as a reference.

jeffarena
  • 501
  • 2
  • 8