Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Parse: an app back-end service

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Introduction to Parse: an app back-end service

Quick overview of Parse's s BaaS offering. Includes pricing information, information on the various Parse iOS SDK classes, code examples, and general best practices to follow when writing an app with a back-end component.

NOTE: Pricing and implementation specifics may have changed since this presentation was created ( 2015/08/20 )

Avatar for Trey Baugher

Trey Baugher

August 20, 2015

Other Decks in Programming

Transcript

  1. Introduction to Parse an app back-end service 08/20/2015 - Trey

    Baugher @ iOS Developers Group, St. Louis 1
  2. Back-End Functionality • Updating static data • User accounts •

    Restoring data • Cross device experience • Backend processing "Cloud Code" 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 2
  3. Why not custom built? • Coding expertise needed1 • Easy

    setup • Scalability & reliability • User experience first 1 I'm sure some of you are multi-language rockstars, I'm not. 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 3
  4. What is Parse code soon, i promise 08/20/2015 - Trey

    Baugher @ iOS Developers Group, St. Louis 4
  5. 3 Feature Buckets • Backend as a service (BaaS) •

    Push notifications • Analytics 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 5
  6. Cloud Code • Functions that live on the server •

    Javascript SDK • Your own API2 • Schedule functions 2 Parse's free tier only allows for 1 function to be run at a time (1 thread), so Cloud code should only be used by your app. 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 6
  7. Free With Limits • 1 million unique push notification recipients

    • 1 cloud function at a time • 30 requests per second • 2TB of file transfer • 20GB of Database Storage • 20GB of File Storage (Images, documents) 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 7
  8. After Limits • Push Notification - $50 per 1 million

    extra • Requests per Second - $100 monthly per 10 reqs/sec (+1 cloud code thread) • File Transfer - $0.10 for every 1 GB extra • Database Storage - $200 for every 20 GB extra • File Storage - $0.03 for every 1 GB extra 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 8
  9. Staying Under the Limits • Limit your requests per second

    • Use the local datastore • No credit card required • Hitting the limits should be success • Inevitable transfer limit 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 9
  10. How's It Work finally some code 08/20/2015 - Trey Baugher

    @ iOS Developers Group, St. Louis 10
  11. App & Account Setup • New account on parse.com •

    Create a new app • App ID added to quick start guide 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 11
  12. Xcode Project Changes • Download the latest framework & add

    dependencies • Add launch code to app delegate @import Parse //link to correct parse app id [Parse setApplicationId:@"YOUR_APP_ID" clientKey:@"YOUR_CLIENT_KEY"]; //no need to use this [PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 12
  13. Creating Classes • Use models to organize your data •

    Create classes in the web panel • Add columns for each property on a model @interface XmasGift : NSObject @property (nonatomic, readonly) NSString* fromName; @property (nonatomic, readonly) NSString* toName; @property (nonatomic, readonly) NSUInteger price; @property (nonatomic, readonly) BOOL giftWrapped; @property (nonatomic, readonly) UIImage* giftPicture; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 13
  14. Parse.com Class Creation onward, to the website! 08/20/2015 - Trey

    Baugher @ iOS Developers Group, St. Louis 14
  15. Using PFQuery to Get Models • Prefer background execution •

    Sort by key • Filter by key • Multi or single object get • Limit amount 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 15
  16. PFQuery Code //predicate constructor available PFQuery* request = [PFQuery queryWithClassName:@"PFxmasGift"];

    //customize request [request whereKey:@"price" lessThan:20]; [request orderByAscending:@"price"]; //avoid retain cycles __weak typeof(self) welf = self; //get it! [request findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error){ if (!error) { //diving into this in a sec [welf giftsLoaded:objects]; } else { //handle error } }]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 16
  17. Working with PFObjects • Queries return an array of PFObjects

    • Access properties like NSDictionary • String property names (error prone) • Inline type conversion (error prone) PFObject *gift = [giftArray objectAtIndex:0]; NSString *fromName = gift[@"fromName"]; BOOL giftWrapped = [gift[@"giftWrapped"] boolValue]; NSUInteger price = [gift[@"price"] unsignedIntegerValue]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 17
  18. Subclassing PFObject .H File //changed inheritance and protocol @interface XmasGift

    : PFObject<PFSubclassing> //added + (NSString *)parseClassName; @property (nonatomic, readonly) NSString* fromName; @property (nonatomic, readonly) NSString* toName; @property (nonatomic, readonly) NSUInteger price; @property (nonatomic, readonly) BOOL giftWrapped; @property (nonatomic, readonly) PFFile* giftPicture;//changed type //suggestion (not required) + (NSString *)parseFromKeyName; + (NSString *)parsePriceKeyName; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 18
  19. Subclassing PFObject .M File //do for all properties @dynamic fromName;

    //will guarantee [registerSubclass] is called before Parse initializes + (void)load { [self registerSubclass]; } //required + (NSString *)parseClassName { return @"PFxmasGift"; } + (NSString *)parseFromKeyName { return @"fromName"; } + (NSString *)parsePriceKeyName { return @"price"; } 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 19
  20. Subclassing PFObject Query Update • Shift strings to one location

    PFQuery* request = [PFQuery queryWithClassName:[XmasGift parseClassName]]; //customize request [request whereKey:[XmasGift parseFromKeyName] isEqualTo:@"Trey"]; [request orderByAscending:[XmasGift parsePriceKeyName]]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 20
  21. End Result • Type safety XmasGift *gift = [giftArray objectAtIndex:0];

    NSString *fromName = gift.fromName; BOOL giftWrapped = gift.giftWrapped; NSUInteger price = gift.price; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 21
  22. What's the Local Datastore #pinning • No core data •

    1 line PFquery add • Lower requests per second [query fromLocalDatastore]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 22
  23. Pin Labels • Easy targeting • Multi-label //pin array [PFObject

    pinAllInBackground:myGifts withName:@"TreysGifts"]; //single pin [gift pinInBackgroundWithName:@"TreysGifts"]; //unpin [PFObject unpinAllObjectsInBackgroundWithName:@"TreysGifts"]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 23
  24. PFImageView • Asynchonous image loading • SDWebImage, PINRemoteImage, AsyncDisplayKit self.giftImageView

    = [[PFImageView alloc] init]; //set placeholder image self.giftImageView.image = [UIImage imageNamed:@"placeholder"]; //database image self.giftImageView.file = gift.giftPicture;//PFFile //starts download [self.giftImageView loadInBackground]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 24
  25. PFConfig • Check for static data updates • Unlock hidden

    functionality (without app update) [PFConfig getConfigInBackgroundWithBlock:^(PFConfig *config, NSError *error) { if (error) { //fallback to cache config = [PFConfig currentConfig]; } BOOL promo = [config[@"doubleGiftDay"] boolValue]; if (promo) { [welf.welcomeMessageLabel setText:@"Double Gifts Today!"]; } else { [welf.welcomeMessageLabel setText:@"Welcome!"]; } }]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 26
  26. Use [PFConfig currentConfig] Update every so often: const NSTimeInterval configRefreshInterval

    = 60.0 * 60.0;//1 hour static NSDate *lastFetchedDate; if (lastFetchedDate == nil || [lastFetchedDate timeIntervalSinceNow] * -1.0 > configRefreshInterval) { [PFConfig getConfigInBackgroundWithBlock:nil]; lastFetchedDate = [NSDate date]; } 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 27
  27. PFUser • Hashed passwords • Email verification • Password reset

    • Duplicate checking • Anonymous user support 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 28
  28. PFUser Signup PFUser *user = [PFUser user]; user.username = @"name";

    user.password = @"pass"; user.email = @"[email protected]"; //custom property user[@"phoneNum"] = @"0-000-000-0000"; [user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { if (!error) { [welf signUpComplete]; } else { //check error, likely username or email taken } }]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 29
  29. PFUser Additional Methods //guarantee anonymous users [PFUser enableAutomaticUser]; [PFUser logInWithUsernameInBackground:@"name"

    password:@"pass" block:^(PFUser *user, NSError *error) { if (!user.emailVerified) { //show email message } }]; //access user PFUser *user = [PFUser currentUser]; //sets currentUser to nil [PFUser logOut]; //user supplies email [PFUser requestPasswordResetForEmailInBackground:@"[email protected]"]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 30
  30. PFGeoPoint • Utilizes core location • Direct conversion from CLLocation

    • One GeoPoint property per object 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 31
  31. PFGeoPoint Code //creation PFGeoPoint *point = [PFGeoPoint geoPointWithLatitude:40.0 longitude:-30.0]; //or

    [PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *geoPoint, NSError *error) { if (!error) { object[@"location"] = geoPoint; } }]; //query filter [query whereKey:@"spot" nearGeoPoint:point withinMiles:10]; //or [query whereKey:@"spot" withinGeoBoxFromSouthwest:point1 toNortheast:point2]; 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 32
  32. Don't Use Everything Provided UI • PFLoginViewController • PFSignupViewController •

    PFQueryTableViewController • PFTableViewCell 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 33
  33. Last Thoughts • Limit framework reliance • Easy data export

    / import • Amazon, Google, Fabric • Offline support 08/20/2015 - Trey Baugher @ iOS Developers Group, St. Louis 34