Fetching every row of a table with Parse and PFQuery
Recently i came across a problem when using the Parse iOS SDK. Unknown to me, the Parse PFQuery object will only return 100 results by default. Which unfortunately, i found out the hard way when one of my apps stopped returning results when the table hit the 100 rows mark. As the Parse documentation says hidden away somewhere:
You can limit the number of results by setting limit. By default, results are limited to 100, but anything from 1 to 1000 is a valid limit:
So what if we want more than 100 results? This question on the Parse support site has a great answer from Héctor Ramos on how to return all the rows in a table with a PFQuery. Although.. as great as the answer is, it only really points you in the right direction. And does not supply a final solution to fetch every result using PFQuery.
I came up with a little sollution using a recursive block, which will use a PFQuery object to query Parse until every result has been returned.
+ (void)findAllObjectsWithQuery:(PFQuery *)query withBlock:(void (^)(NSArray *objects, NSError *error))block { __block NSMutableArray *allObjects = [NSMutableArray array]; __block NSUInteger limit = 1000; __block NSUInteger skip = 0; typedef void (^FetchNextPage)(void); FetchNextPage __weak __block weakPointer; FetchNextPage strongBlock = ^(void) { [query setLimit: limit]; [query setSkip: skip]; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { if (!error) { // The find succeeded. Add the returned objects to allObjects [allObjects addObjectsFromArray:objects]; if (objects.count == limit) { // There might be more objects in the table. Update the skip value and execute the query again. skip += limit; [query setSkip: skip]; // Go get more results weakPointer(); } else { // We are done so return the objects block(allObjects, nil); } } else { block(nil,error); } }]; }; weakPointer = strongBlock; strongBlock(); }
So to use this method we can simply do the following:
PFQuery *query = [PFQuery queryWithClassName:@"myClassName"]; [ParseProxy findAllObjectsWithQuery:query withBlock:^(NSArray *objects, NSError *error) { if(!error) { NSLog(@"Loaded All Objects: %@",objects); } }];
Easy!
















