Search code examples
iosobjective-cuiviewcontrollerparse-platform

Paginate parse queries using a regular UIViewController


I have a UIViewController with a tableview in it. I populate the tableview using the regular methods. I call my query using a method called loadEntries.

The problem is that the amount of entries the loadEntries can be more then tens of thousands.

I would rather not change my ViewController to a PFQueryTableViewController, exception can be made if there is a sneaky way to change from UIViewcontroller to PFQueryTableViewController.

so my questions is: Is it possible to implement pagination with parse.com queries(Not using PFQueryTableViewController), if yes, how?


Solution

  • You need to take a look at the skip parameter of PFQuery as discussed here in Parse's PFQuery Documentation.

    You can run the query the first time as just a count, and then you will be able to determine how many pages of data you'll have.

    Then, you can run the query with skip and 'count' values based on the "page" the user is currently viewing.

    Something like this:

    - (void)countRecords {
        PFQuery *query = [PFQuery queryWithClassName:@"className"];
        // Other query parameters assigned here...
        [query countObjectsInBackgroundWithBlock:^(int count, NSError *error) {
            // Do better error handling in your app...
            self.recordCount = count;
            self.pageCount   = count / self.recordsPerPage + 1;
            [self loadRecordsForPageIndex:0 countPerPage:self.recordsPerPage];
        }];
    }
    - (void)loadRecordsForPageIndex:(NSInteger)pageIndex countPerPage:(NSInteger)count {
        PFQuery *query = [PFQuery queryWithClassName:@"className"];
        // Other query parameters assigned here...
        query.limit    = count;
        query.skip     = pageIndex * count;
        [query findObjects... // You should know this part
    }
    

    In the above example, -countRecords gets the current count of the records matching your query and then automatically calls -loadRecordsForPageIndex:countPerPage:. Later, when the user navigates between pages of data, you would call this again, passing in the new pageIndex and count (records per page) values. You could refactor this to keep referencing self.recordsPerPage as the instance variable it is or not.

    From Parse.com directly:

    Caveat: Count queries are rate limited to a maximum of 160 requests per minute. They can also return inaccurate results for classes with more than 1,000 objects. Thus, it is preferable to architect your application to avoid this sort of count operation (by using counters, for example.)

    MY CAVEATS:

    1. The default value for limit is 100.
    2. The maximum allowed value for limit is 1,000.
    3. The default value for skip is 0 (zero).
    4. The maximum allowed value for skip is 10,000.
    5. Therefore, you cannot reliably query more than 11,000 objects with one single, unmodified query. (You can get advanced and search using createdAt or something, but those would be PFQuery instances with different constraints.)