Best RestKit setup

662 Views Asked by At

I would like to use RestKit 0.20 on my app but I am a bit confused on how the pieces fit together. Each one of my view controllers needs to get data from the server each with their own route on the server returning a different object. I would like to keep all of the server requests away from the view controllers so I can manage them centrally (but open to another setup if it makes sense). Right now I have the following setup but I am pretty sure there is a better way to go about it using RKObjectManager and RKRouter :

1) Each view controller triggers a method in a Gateway object that is dedicated to it.

2) The method will create a request and a response map. Then a request and response description and finally a request operation that uses a manually created NSURL.

3) In the success block I pass the response to the view controller with an NSnotification.

Is there a better setup? Can I just use one RKObjectManager for all the request? How does that work? Do I put it in a separate method in my gateway? Is there a better way to get back to my view controller then NSNotification?

Sorry if some of these are very basic.

1

There are 1 best solutions below

2
On BEST ANSWER

I would suggest the following structure (using Instagram as an example):

1) first of all split all your requests based on the "Resource" you use e.g. Users/Comments/Likes, etc

2) For each "Resource" create a separate class, subclass of RKObjectManager, for example UsersManager, CommentsManager, LikesManager (all inherited from RKObjectManager)

3) Define extra methods on every manager, that you will use from View Controller. For example, for loading "likes" resource for user, you'd define this method in LikesManager (or UserManager) -- this is very opinionated decision, and it's really up to you.

- (void)loadLikesForUser:(User *)user
                 success:(void (^)(NSArray *likes))successCallback
                 failure:(void (^)(NSError *error))failureCallback;

4) Implement this method and call appropriate methods using self, because you've created a subclass of RKObjectManager class and have access to all basic methods.

    [self getObjectsAtPath:@"/resources/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        // pass mappingResult.array to the successCallback
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        // pass error object to the failureCallback
    }];

5) In your view controller, you'd call this like

    [[LikesManager sharedManager] loadLikesForUser:user success:^(NSArray *likes) {
        self.likes = likes;
        // work with likes
    } failure:^(NSError *error) {
        // handle error
    }];

Notice that you don't do any stuff with NSNotification, as it'll be a bad design decision in this kind of situations.

Generally speaking you can put all of your requests in a subclass of RKObjectManager, if you have very few of them, but if you have more than 5-6 requests, you'll find it tedious and hard to manage to keep all of them in one file. So that's why I suggest to split them based on a Resource.

UPDATE Based on questions asked in comments, providing answers here

a) Where to set Base URL?

Base URL is a property on instance of RKObjectManager, so you definitely want to set it before making any requests to API. To me ideal place would be at the initialization of RKObjectManager instance.

b) Where to define Object Mapping?

Again it's up to you. Answer to this question is very opinionated. I'd consider 2 options:

  1. create a separate class to hold all your objects related to mappings, like MappingProvider. Then whenever you create RKResponseDescriptor or RKRequestDescriptor, you'd just access properties of MappingProvider to get your mappings.
  2. Define mappings in manager's class, because you'll assign them to the RKResponseDescriptor instances that will be used in this manager.

UPDATE: Check out this blog post on RestKit setup: http://restkit-tutorials.com/code-organization-in-restkit-based-app/