drewish
drewish

Reputation: 9380

How to fetch pages of results with RestKit?

I'm using RestKit 0.10.1 and I'm looking for some sample code for dealing with web service that paginates results. I've got GET requests fetching the first page with no parameters and sticking them into a UITableView. Ideally when I get to the bottom of a page it would fetch the next page and insert those values at the bottom.

I guess I should clarify that I'm more concerned about how to do the fetching than how to tack them onto the end of the table, but if there are suggestions for that I'd love to hear them. Also these records aren't being stored in managed objects, they're just in memory.

Update: After switching my Google searches from "paging" to "pagination" I came across RKObjectPaginator and realized the API I'm dealing with is pretty brain dead and doesn't output any counts or data about which page you're on or its size.

Upvotes: 2

Views: 1320

Answers (1)

Paul de Lange
Paul de Lange

Reputation: 10633

As you say, you can normally use RKObjectPaginator. But sometimes, as you also say, it doesn't work very well if your API is not compliant.

You can completely customize the paginating by doing something like the following:

1) Create a subclass of RKObjectPaginator (or your own class if you want to go down that route).

2) The key is to override this delegate method

- (void) objectLoader:(RKObjectLoader *)loader willMapData:(inout __autoreleasing id *)mappableData;

3) In this method, you take the mappableData object and find the "next page" parameters. However you do this is up to you. Below is an example using the Bing API.

- (void) objectLoader:(RKObjectLoader *)loader willMapData:(inout __autoreleasing id *)mappableData {
    NSMutableDictionary* d = [[*mappableData objectForKey: @"d"] mutableCopy];

    NSString* next = [d objectForKey: @"__next"];

    if(!next) {
        currentOffset = 0;
    }
    else {
        NSDictionary* params = [next queryParameters];
        perPage = [[params objectForKey: @"$top"] intValue];
        currentOffset = [[params objectForKey: @"$skip"] intValue];
    }
}

The important thing is to map, the data before passing it on to your target object. This effectively allows you to do two maps with one response (one map to the paginator object, and one map to your data model).

Upvotes: 4

Related Questions