Our post from two days ago about Parse powered iOS tables was so popular, we decided to follow up with a more in-depth tutorial. The screencast above will walk you through the steps of setting up a PFQueryTableViewController to display objects from a Todo class in your Parse application.
Here’s what the tutorial covers:
Setting up the table class
Adding objects using the Data Browser
Using pagination
Using pull to refresh
Customizing the cells
Customizing the query
In literally minutes, you’ll be pulling down data from Parse and displaying it in a UITableView.
As the new year approaches, the Parse team is still hard at work improving the platform. We’ve just pushed out a series of improvements to PFQuery and ParseQuery. Both classes are now even more resilient to a wide variety of network conditions and failures. In most cases, Parse developers shouldn’t need to worry about the network anymore. We’ve also added cancel methods so that you can abort a query at any time. Stay tuned for the same improvements to PFObject and ParseObject coming soon!
On another note, the team here wants to thank all of our developers for their support. Parse is barely over six months old and we’ve already gotten phenomenal traction with the mobile development community. We couldn’t have done it without the support of our early adopters and passionate users worldwide. Thank you!
Pull out your iPhone and open an app. What do you see? Most likely, you’re looking at a UITableView, filled with data that was pulled down from a server. Everything from Twitter to Foursquare to the Quora app is chock full of these UI constructs.
At Parse, we’re obsessed with making data-driven apps a cinch to develop. At the end of the day, users of a Parse powered app are interacting with UI elements that display data from Parse. But, there’s a lot of code that goes into wrangling the Parse objects into those UI elements.
That is why I’m excited today to announce the first Parse User Interface class for iOS: PFQueryTableViewController. With this class, you’ll be able to setup a UITableView that displays your Parse data in a fraction of the time it used to take.
This class inherits from UITableViewController but comes with a bunch of handy methods that make it easy to query, paginate, and display PFObjects. All you have to do is override a few simple methods, and the rest is taken care of for you. For example, here’s a simple table for displaying Todo items:
@interface SimpleTableViewController : PFQueryTableViewController
@end
@implementation SimpleTableViewController
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
// This table displays items in the Todo class
self.className = @"Todo";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = NO;
self.objectsPerPage = 25;
}
return self;
}
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.className];
// If no objects are loaded in memory, we look to the cache
// first to fill the table and then subsequently do a query
// against the network.
if ([objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[query orderByDescending:@"createdAt"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
object:(PFObject *)object {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
}
// Configure the cell to show todo item with a priority at the bottom
cell.textLabel.text = [object objectForKey:@"text"];
cell.detailTextLabel.text = [NSString stringWithFormat:@"Priority: %@",
[object objectForKey:@"priority"]];
return cell;
}
@end
And here’s what the result looks like:
With this small amount of code, you get the following:
Pagination
Pull-to-Refresh
Caching
An easy way to create cells directly from PFObjects
Many mobile apps have an awareness of where they are in the world. Often, we want to associate that location with data, like when we geotag a photo. Other times we want to use that location information to find out about the things nearby. To help you with situations like this we’ve added geo features to Parse.
Now, associating locations with your data and performing geo queries is easy. To associate a latitude / longitude location with an object you merely create a PFGeoPoint and store it in your object like this:
Once you’re done associating locations with your objects, you can then issue queries to find out which objects are near a location. If you have a user location and want to find out what’s within a 10 mile radius, your code may look something like this:
Whether you’re keeping track of points, gold coins, or sheep, using
a counter is a pretty common occurence in mobile development.
Although a seemingly simple concept, counters can be tricky to
get right especially if you want to update them in multiple places or on
multiple devices.
Today we’ve added a simple but very powerful feature: atomic increment
operations. Suppose we have a GameScore object that we’ve created like
so:
Now, suppose the player has advanced in the game and earned an extra 10
points. We’d like to update their score on the server. Before, you’d
have to do something like the following:
Not only is this cumbersome but it can be problematic if another part of
your game or another device has updated the score in the meantime. The
above update would squash the score to what it thinks is right!
Now, you can just do the following and let Parse take care of the
details:
Every time you hit a mobile network, it slows your users down and introduces another point of failure. So when you’re designing your application, you need to take advantage of every opportunity to omit needless requests.
Parse’s philosophy is to help make this easier by providing standard ways to reduce network requests. One example is caching queries, which lets you avoid resending requests you’ve already sent. Another example, which we’ve launched in the most recent version of the Parse SDK, is include functionality, inspired by the Ruby on Rails :include option.
When you have relational data, the includeKey: method in iOS and the include method in Android lets you specify that data from a relational field should be also fetched at the time of the initial query. For example, suppose each Song object has an associated Band in the band key. You might have an app that shows the top ten songs by sales, and you want to also retrieve information about the band without issuing an extra query. To fetch this data in iOS:
PFQuery *query = [PFQuery queryWithClassName:@"Song"];
// Retrieve the top songs by sales
[query orderByDescending:@"sales"];
// Limit to retrieving ten songs
query.limit = 10;
// Include the band data with each song
[query includeKey:@"band"];
// Issue the query
[query findObjectsInBackgroundWithBlock:^(NSArray *songs, NSError *error) {
if (error) return;
// Songs now contains the last ten songs, and the band field has
// been populated. For example:
for (PFObject *song in songs) {
// This does not require a network access.
PFObject *band = [song objectForKey:@"band"];
}
}];
Our goal is to provide developers with an easy and efficient way to get their job done. We’re always interested in more feedback on how we can help you build great apps, so if you have great ideas for how Parse could help you, get in touch.