How I use (and abuse) RestKit.
What is RestKit?
RestKit is an open source framework designed to make consuming RESTful API’s easy. Which thankfully it does fairly well. Just point it at a URL, do some simple JSON to object mapping, send off an asynchronous request and sit back as your response is turned into a tidy object. However the examples provided, much like Apple’s, leave something to be desired. The examples assume you know MVC and will use it instead of slapping everything in the App Delegate. But even if you keep your classes loosely coupled it still takes a moment to figure out how to divide responsibility when using RestKit.
I don’t have all the answers because the best parts of my RestKit setup I picked up from Taras Kalapun. If you follow his example though I would advise you to not use dependency injection because well not only does Objective-C have late binding, it has dynamic binding. Also Taras’ podfile in his blog post is outdated as I’m using RestKit 0.10.1 in this post.
Setting Up RestKit
First add RestKit to your project by adding it to your Podfile using CocoaPods. Run pod install, open the workspace file and not the project file then add
<RestKit/RestKit.h> to your App Delegate and run. If everything installed correctly then you shouldn’t see any errors.
platform :ios pod
Next configure the Object Manager by setting a base url and MIME types. Now this is where we diverge from the example. Instead of throwing all the details of our object mapping into the App Delegate we will increase our data model classes’ cohesion by making the mappings a class method. This could probably be cleaned up a little more but it is already much better than the example because we now have one less file to change when we need to change our object’s properties.
We also added the serialization mapping and the routes so that with these few lines we only have to tell our object loader if we want to GET, PUT, or POST.
Now RestKit used to handle both ‘error’ and ‘errors’ messages but after 0.10.0 was introduced they improved object mappings by giving errors their own context however it is difficult to map two top level key paths with the new code. Check out my StackOverflow post about this if you want to learn to support Rail’s pluralization of both errors and error.
I’m going to skip user authentication right now because it is more dependent on your setup and honestly I don’t like the way I’m handling it myself right now.
Usually the next step is to setup a basic UITableViewController and send a request to populate the table view on viewDidAppear but first we will setup up an intermediate object to handle fetching and storing our objects. This is important because once we separate this functionality we will be able to share this intermediate object between classes such as a table view and a map view. If you have more questions about this you can check out Matthijs Hollemans excellent post about how to make your classes talk to each other.
There are a couple of things going on here. First we are hiding the actual data structure that is holding the articles. Who knows we might use a set to store articles later. Next we are recieving parsed objects from RestKit and making a mutable copy so we can easily change it later. Then since in this case we are able to check the previous existence of an article we only have to make one public method for saving an article. Since we specified our routes before we just have to tell the object manager if we want to put or post our article. You will also notice that with the block notation I’m creating a weak reference to self and checking it to make sure it exists for use in our blocks to prevent retain cycles.
This last part isn’t too interesting but I’ll show it anyways. First you can refresh your data controller or data source with this method. You’ll notice that the since our data controller takes a block argument it is easy to do things like showing an activity indicator, refresh your view on completion or show an alert on error. Then you can simply access the data controller from your view controller or turn it into your view controller’s data source and move this last method into your data source. Lastly you could bind your views to your model using Reactive Cocoa but thats another blog post.