This post is intended to be a very brief introduction to the Parse SDK for iOS. It just touches the most basic points when setting up your app with Parse. Refer to the official guide for an in depth view of what's possible with Parse.

Storing data on Parse is built around the PFObject. Each PFObject contains key-value pairs of JSON-compatible data. This data is schemaless, which means that you don't need to specify ahead of time what keys exist on each PFObject. I highly recommend creating classes for your models derived from PFObject to avoid inconsistencies with manually handling key value pairs. To do so, just subclass PFObject and implement the PFSubclassing prototype. Define all columns on the backend as @dynamic properties in the class like so:

@interface QBQuote : PFObject <PFSubclassing>

// Properties on backend
@property(nonatomic, strong) NSString *text; // String column on the backend
@property(nonatomic, strong) QBImage *image; // Pointer<Image> on the backend
@property(nonatomic, strong) NSArray *tags; // Array<Tag> on the backend

// Computed properties (no need for `@dynamic` in implementation)
@property(nonatomic, readonly) BOOL favorite;

@end

Of course, you will need classes like QBTag and QBImage registered for their respective tables on the backend.

@implementation QBQuote
@dynamic text, image, tags;

#pragma mark - Parse

+ (void)load {
    // Required to register the sub class with Parse
    [self registerSubclass];
}

+ (NSString *)parseClassName {
    // Name of class on the backend
    return @"Quote"; 
}

+ (PFQuery *)query {
    PFQuery *query = [super query];

    // Include some child keys to avoid making another requests for them in the future
    [query includeKey:@"image"];
    [query includeKey:@"tags"];

    // Load from the cache if network requests fail
    query.cachePolicy = kPFCachePolicyNetworkElseCache;

    return query;
}

@end

This ia all you need to start making requests for data from the backend. I like to keep all my backend logic in the class, so I have a few more methods here for loading data from the backend. Here's a sample implementation of loading the data using PromiseKit (Check out this post for a quick overview). Here is how you would retreive objects (using Parse-PromiseKit):

#pragma mark - Backend

+ (PMKPromise *)loadWithFilterBlock:(void (^)(PFQuery *query))filterBlock page:(int)page {
    PFQuery *query = [QBQuote query];
    query.limit = kQBQuotePerPageLimit;
    query.skip = page * kQBQuotePerPageLimit;

    // Apply additional filters
    if (filterBlock) {
        filterBlock(query);
    }

    return [query promiseFindObjects];
}

+ (PMKPromise *)countWithFilterBlock:(void (^)(PFQuery *query))filterBlock {
    PFQuery *query = [QBQuote query];

    // Apply additional filters
    if (filterBlock) {
        filterBlock(query);
    }

    return [query promiseCountObjects];
}

Loading items is now just a simple call like this:

[QBQuote loadWithFilterBlock:self.filterblock page:self.numberOfQuotes / kQBQuotePerPageLimit].then(^(NSArray *quotes) { ... }];

Need to save objects? Just update the properties, and call saveEventually and it will take care of handling the network outages and other faults. An important thing to keep in mind when creating/updating objects is the permission for the objects. Use the ACL property on PFObject to control who has access to the object. For example, to allow write access to an object by only the current user:

quote.ACL = [PFACL ACLWithUser:[PFUser currentUser]];  
[quote.ACL setPublicReadAccess:YES];