Tutorial: Make a Remote Data Table in Minutes

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.

You can find the entire project on the TodoTable Github page. So, feel free to fork, experiment, and play with the example. Also, check out the iOS Guide for more details.

James Yu
December 30, 2011

Query Improvements and Happy New Year

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!

Happy New Year!

Ilya Sukhar
December 30, 2011

Parse Powered iOS Table Views

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 ([self.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

Read more about the class in our iOS Guide and also the iOS Documentation.

James Yu
December 28, 2011

Geo Queries

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:

PFGeoPoint point = [PFGeoPoint geoPointWithLatitude:37.77 longitude:-122.41];
PFObject *placeObject = [PFObject objectWithClassName:@"PlaceObject"];
[placeObject setObject:point forKey:@"location"];
[placeObject setObject:@"San Francisco" forKey:@"name"];
[placeObject saveInBackground];

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:

PFGeoPoint *userGeoPoint = [PFGeoPoint geoPointWithLatitude:37.856965 
                                                  longitude:-122.483826];
PFQuery *query = [PFQuery queryWithClassName:@"PlaceObject"];
[query whereKey:@"location" nearGeoPoint:userGeoPoint withinMiles:10.0];
NSArray *placeObjects = [query findObjects];

At this point, you have a sorted list of all the objects nearby and you’re good to go!

iOS documentation, Android documentation, or REST documentation covers more of the details.

If you have any ideas or suggestions for improving Parse, let us know!

Henele Adams
December 9, 2011

Counters on Parse

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:

PFObject *gameScore = [PFObject objectWithClassName:@"GameScore"];
[gameScore setObject:[NSNumber numberWithInt:1337] forKey:@"score"];
[gameScore saveInBackground];

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:

int newScore = [[gameScore objectForKey:@"score"] intValue] + 10;
[gameScore setObject:[NSNumber numberWithInt:newScore] forKey:@"score"];
[gameScore saveInBackground];

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:

[gameScore incrementKey:@"score" byAmount:[NSNumber numberWithInt:10]];
[gameScore saveInBackground];

That’s it!

Read more about the new atomic increment operators in the iOS documentation, Android documentation, or REST documentation.

Let us know what you think!

Ilya Sukhar
December 7, 2011

Including Related Objects in Queries

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"];
    }
}];

Read more about relational queries in the iOS documentation, Android documentation, or REST documentation.

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.

Have fun building apps!

Kevin Lacker
December 6, 2011

Archives

Categories

RSS Feed Follow us Like us