Trying to make a POST request with RestKit and map the response to Core Data

Vlad Bogdan picture Vlad Bogdan · Dec 19, 2012 · Viewed 10.3k times · Source

I am using RestKit framework and i want to make a POST HTTP request. The response is JSON. I want to put the JSON response automatically in the CoreData.

I don't know exactly what methods to call to make the request. I know that I should use RKObjectManager's methods but I didn't find the right one.

I found this method postObject:delegate: but I don't what the object to pass as parameter. I also find this method in documentation: loadObjectsAtResourcePath:usingBlock: but I can't use it because it tells me:

No visible @interface for 'RKObjectManager' declares the selector 'loadObjectsAtResourcePath:usingBlock:'

Answer

Blake Watters picture Blake Watters · Dec 20, 2012

Vlad - First off, let's get an answer in place to your original question:

I assume that you are working off of RestKit 0.20.0, but are familiar with the RestKit 0.10.x API's and are consulting outdated information. The first place that you should be turning is to RKObjectManager.h -- the headers are always going to be up to date and will contain docs about what methods are available. Next, you can always view the latest documentation built from the source code on the latest API docs site.

What you want to do here is create an RKObjectRequestOperation:

NSDictionary *dictionary = @{ @"firstParam": @(12345), @"secondParam": @"whatever"};
NSMutableURLRequest *request = [objectManager requestWithObject:nil method:RKRequestMethodPOST path:@"/whatever" parameters:parameters];
RKObjectRequestOperation *operation = [objectManager objectRequestOperationWithRequest:request success:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
    NSLog(@"Loading mapping result: %@", result);
} failure:nil];

If you are trying to target Core Data, then you'll want to use RKManagedObjectRequestOperation and managedObjectRequestOperationWithRequest:success:failure:. There are additional examples available in the README.md on the RestKit Github site and in the header docs and there is a metric ton of code in the unit tests for reference as well.


Next, in response to the comments from JRG-Developer:

Ahem, this is a really terrible answer for a number of reasons. (Disclaimer: I am the principal developer of RestKit)

First of all, what version of RestKit are you using? If you are using a recent version (i.e. in the 0.20.x pre-release series) then the methods for loading collections of objects have been replaced with better names: getObjectsAtPath:. This is fully documented in both the API documentation (Making Requests by Path) and in the 0.10 to 0.20 migration guide.

I suspect that the original issue here stems from referring to outdated documentation along with recent code.

Next, the stack of technologies you are recommending is far more complicated to setup and use to accomplish the same things that RestKit provides for you once you actually understand the library.

Let's take a look at this point by point:

  1. AFNetworking

    • AFN is a great, lightweight library for performing asynchronous networking operations. If you think of RestKit as a toolbox containing a number of tools for implementing client side API's, then AFN is the hammer.
    • I have tremendous respect for AFN and in RestKit 0.20.x, we dumped our aging homebrewed networking library in favor of AFNetworking because its design was superior to the RestKit custom networking stack that has been hanging around since iOS 3.0. AFN alone, however, does not provide you with enough firepower to completely implement an API that integrates with Core Data without having deep knowledge of Core Data and implementing a large amount of synchronization code yourself.
    • RestKit's object mapping system gives you a performant, consistent API for configuring these synchronization activities rather than implementing them yourself. This enables some serious performance optimizations that I will return to later.
  2. JSONKit

    • JSONKit is another library that I hold in high regard, but it's probably not worth your time. When compared to NSJSONSerialization, the JSON parsing speed of JSONKit is superior -- but only by milliseconds.
    • As someone who has implemented large API clients for widely deployed apps, I can tell you that your time is not going to be spent in JSON serialization/deserialization, but in the code that processes your JSON once it has been deserialized.
  3. MagicalRecord

    • MagicalRecord is a Core Data convenience library that provides shorthand accessors for existing functionality in Core Data. It is not going to improve your life once you get into the nuts and bolts of what it really takes to implement an HTTP to Core Data synchronization scheme. Your problems will have nothing to do with the syntax of Core Data fetch requests being too verbose, it being inconvenient to maintain a reference to your managed object context, or with getting the Core Data stack setup.

So let's talk about what the real problems are with implementing an iOS / OS X application that models an API into Core Data for a moment:

  1. Asynchronous Access
    • The first problem you are going to run into is that you are used to programming in a synchronous, main thread oriented way, but now you need to fire off an AFNetworking request that loads your JSON, but then load it into your object model. No problem, just wait for the AFJSONRequestOperation to hit you back in the success block and update Core Data, right? Wrong. Now you are doing your network I/O asynchronously, but then doing the CPU Intensive task of updating your data model on the main thread. Now your app performance sucks and you don't know what to do about it. How do you move that synchronization into the background? How do you notify the UI once its done?
  2. Error Handling
    • What happens when you hit an error? What do you do when you get a network error? What do you do when the network operation completes, but you hit an error during Core Data access? How are you going to handle it? Are you going to put this error handling code into all of your controllers? How are you going to encapsulate all that logic?
    • How are you going to handle errors that are returned by your server?
  3. Unique Object Identification
    • Okay so now you've loaded your JSON and you want to put it into Core Data. Great. How are you going to differentiate existing objects within the store versus new ones that need to be created?
    • If you get this wrong, you now have duplicate objects.
    • If you get this right, but do it from a main thread context, your UI is blocked and your performance sucks.
    • If you get this right, but do it on a background thread you may have concurrency problems.
    • If you get this right, but hit the persistent store with fetch requests to identify your unique objects you now have a performance problems.
  4. Deleting Orphaned Objects
    • Once you synchronize your data set with the server, how are you going to take care of removing dead objects from the local store that no longer exist on the server?
  5. Performance
    • As I've alluded to in several earlier parts of this rant, all roads will eventually lead to performance. If you are actually trying to build something that will work and delight users on a large scale, you are going to have to contend with serious performance problems. Giddy up.

There are a number of additional problems you will have to contend with once your application is successful, including testability, maintainability, etc. How much are you thinking about these things?

I guess my main point here is that is (from my perspective) far too common to hear insane cheering or jeering coming from the peanut gallery about how to tackle fundamental engineering problems. The reality is that the solution to problems with essential complexity will have a learning curve that is relative to that of problem being approached.

It is far, far easier to take a discrete slice of functionality and nail down a satisfactory solution than it is to try and approach a larger, but more interesting problem.

But that does not mean that you are going to produce a more robust solution by lashing together a bunch of libraries that you have heard provide nice implementations of a subset of a problem than a larger approach to the aggregate problem.

Why hasn't anybody Open Sourced their own AFN/JSONKit/Core Data/MagicalRecord mashup and blow RestKit out of the water if they are so much better than RestKit?

I'm afraid that the sober truth is: it just ain't that easy.

Cheers!