All -
After spending quite a bit of time focused on Rails development over the last few months, I've swung back into iOS land and have a number of RestKit changes + enhancements to discuss. Most of these changes are currently available on the development branch except where noted. Let's dive in…
1) First the annoying housekeeping.., There have been many API cleanups and deprecations.
A fair amount of logic was duplicated across the code base for handling baseURL's, resource paths, and query parameters. All of this logic has been centralized into the RKURL class and the tests + documentation have been blown out. RKRequest and RKObjectLoader are now initialized with RKURL's instead of strings.
Many C-style methods (i.e. RKPathAppendQueryParams, RKPathInterpolateWithObject) have been replaced with category methods or had their functionality migrated into a new home. Most changes should show up as warnings with a pointer to the replacement methods.
2) Support for Resource Path based mapping selection. Rather than relying so heavily on key-value coding to select mappings, RestKit can now evaluate the URL you are loading against a pattern to determine what mapping it use. Registration of patterns such as @"/users/:userID" (just like the routing for generation) are supported.
This means we now fully support mapping content that is _not_ uniquely identifiable by keyPath without having to tell the object loader which mapping to use (see the RKTwitter examples on the development branch).
3) New mapping groupings via contexts. Since the OM 2.0 engine last summer, RestKit has leaned on key-value coding very deeply for all object mapping selection needs. As the project has grown, it has become clear that its not enough and can be highly inconvenient if you do not control your JSON structures. We have resolved this issue by supporting a number of new mapping contenxs on the mapping provider. In addition to the traditional key path object mapping registrations and serialization mappings (keyed by object type), there are now resource path pattern mappings (see above), as well as an error mapping and a pagination mapping (more on this in a minute).
The error mapping is used whenever RestKit encounters a 4xx or 5xx status code with a parseable MIME type. The mapping will be applied to the payload to allow you to flexibly map the content out and then that mapping result is enclosed into an NSError and sent up the stack.
All object mapping collections managed by the provider are implemented using a set of primitive 'context' methods that manipulate a namespaced NSMutableDictionary. This means that you can extend the mapping provider via category rather than subclassing. RestKit is being used in a number of SDK's and this should enable such use-cases more cleanly.
4) De-emphasized the delegate and added blocks all over the place. Many methods were deprecated that took an RKObjectLoaderDelegate or RKRequestDelegate as a secondary argument. We have tried to provide block property alternatives for all the highly used delegate callbacks as well as the workhorse methods on RKClient and RKObjectManager. We have deprecated a number of methods on the manager (i.e. postObject:mapResponseWith:) that duplicate the functionality of creating an object loader and configuring properties to combat an API explosion.
5) Introduced the RKObjectPaginator component. This component is initialized with a resourcePathPattern and an object mapping provider and is capable of performing paginated retrieval of subsets of objects in a larger collection. The mapping provider now has a paginationMapping where one configures the paginator to extract metadata from the payload (i.e. number of objects in the collection, total number of pages, etc). The tests has a thorough example of how to use this and I'll be adding one to RKCatalog shortly.
6) Nasty singleton coupling has been cleaned up almost everywhere (there is some work left in the Core Data ActiveRecord helpers). Going forward RKRequest and RKObjectLoader should *never* have knowledge of the client/object manager.
7) Replaced the custom LibXML parser with an existing open source library. The parser never really worked that well and contained some truly nasty code. We've integrated a library rather than burning additional cycles on the parser.
8) Object mapping operations are now queued and executed independently of network loaders. Requests are finished and removed from the request queue as soon as loading completes and then added to a serial queue for object mapping. This ensures that there are not a ton of concurrent mapping operations executing at once and that the request queue doesn't fill up with requests that are fully loaded, but not yet mapped. (This is part of the table controller branch being merged currently)
Last but not least is the table controller code base that has been in exile on the GateGuru fork for months. This component allows you to quickly and easily build UITableView's using local objects, object loaders (pure data driven network table), and a network refreshed, NSFetchedResultsController backed Core Data table view. This is a very large new piece of funcionality and underpins the entire GateGuru application UI. Essentially it uses the object mapping engine to bind your local domain objects to table view cells in much the same way parsed JSON/XML are bound to objects. Filtering, searching, sorting, etc. are all very cleanly integrated into the stack as well as some additional bells and whistles such as pull to refresh and swipe menus on the cells.
This component is so big and we are so excited about it that GateGuru is affording me some time out to author a new tutorial and sample code to show it off. I'll be rolling onto this effort later today when I finish merging the table controller into the development branch.
I will have more news on the table controller and tutorial front as it develops.
Cheers,
Blake
--
Blake Watters
VP Engineering, GateGuru
Interested in building the mobile travel experience of the future? We're hiring!