Perspective on Parse Local Datastore for iOS

This is in part an excerpt from the parse documentation. This small post is based on my solution architecture perspective on the Parse Local Datastore* for iOS.

Why use a local Datastore when using parse and iOS…

Usually, we use local Datastores to keep the information when our App is offline (no connection, airplane mode, etc.).

But other problematic scenarios may be solved using this approach, such as – performance issues.

From my experience and many reads on the Internet, developers simply integrate parse’s InBackground method to query’s and thus “free flow” the

App and virtually speed up the screen presentations. Not a bad idea.

But this approach may be fundamentally wrong from start and for a very simple reason… timing.

When you use the InBackground method without pinning, your App may present the next screen faster than the query, thus leaving your scene empty or simply presenting you with errors.

I’ve personally lived this with my partner in crime more than a few times, and this is not good, nor fun. Here’s an example from the website:

 PFQuery *query = [PFQuery queryWithClassName:@"GameScore"];
 [query whereKey:@"playerName" equalTo:@"Dan Stemkoski"];
 [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) …

Aware of this potential shortcoming, the need for a local Datastore is great news (in some cases caching with parse is great, but this subject will be for a later write up, as caching has key limits. I hope this will change in time to become more powerful.).

Finally, this is not a parse “how-to”, so if you’re not comfortable on the subject, I highly recommend going on and read up on the solution, it is very simple to understand. Here we go:

[PFObject pin] / [PFObject unpin]

Instead of just creating a “standard” PFQuery and “waiting” for results or going in background, we can now “pin” (save data) and “unpin” (remove data). Simply:

  • [PFObject pin] persists PFObjects to the Local Datastore.
  • [PFObject unpin] removes them.
  • Once pinned, we can access the data with a normal PFQuery.

The following is a simple example from documentation. Key references are in bold to easily view the information.

PFQuery *query = [PFQuery queryWithClassName:@"Feed"];
 // Pin PFQuery results
 NSArray *objects = [query findObjects]; // Online PFQuery results
 [PFObject pinAllObjectsInBackground:objects];
 // Query the Local Datastore
 [query fromLocalDatastore];
 [query whereKey:@"starred" equalTo:@YES];
 [[query findInBackground] continueWithBlock:^id(BFTask *task) {

Does my data persist when users quit the App?

Yes. Parse’s documentation confirms the following:

“Pinned PFObjects will remain accessible while offline — through app exits and restarts — until they are unpinned. Subsequent saves, updates, or deletes will keep your Parse Local Datastore results up-to-date.”

Can I update the information?

Yes. Objects can be updated using the saveEventually method. As confirmed by parse, the following will update the Local Datastore and then remotely.

The following is a simple example from documentation. Key references are in bold to easily view the information.

 feedItem.starred = YES;
 // No network connectivity
 [feedItem saveEventually];
 PFQuery *query = [PFQuery queryWithClassName:@"Feed"];
 [query fromLocalDatastore];
 [query whereKey:@"starred" equalTo:@YES];
 [[query findInBackground] continueWithBlock:^id(BFTask *task) {
 // "feedItem" PFObject will be returned in the list of results

What to remember

The key thing to remember is that enterprise and solutions similar to Parse gives us developers great tools, but we have to make sure we use them intelligently.

Methods such as findObjectsInBackground can blindfold developers into thinking all is good – as long as the connection time and speed is good. When it’s not, that’s when other solutions need to be implemented.