Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Connecting to a REST API in iOS


Published on

This is a presentation I gave at the combined Tokyo Rubyist / iOS Event.

Connecting to a REST API in iOS

  1. 1. Connecting an iOS App to a REST API Matthew Gillingham @gillygize / @TokyoiOSMeetup
  2. 2. The Basic Workflow1.Use a networking library to connect to the web service.2.Download the server response (probably JSON or XML).3.Parse the response by transforming it into an NSDictionary or NSArray.4.Turn the dictionary in a data model class.5.Store the data locally (probably with Core Data)
  3. 3. Networking Libraries• AFNetworking• ASIHTTPRequest (the old standard, no longer maintained)• MKNetworkKit• NSURLConnection• FSNetworking• libcurl
  4. 4. AFNetworking• Actively-maintained and widely used• Simple interface• Made with REST APIs in mind (using AFHTTPClient)• Parses JSON automatically
  5. 5. AFNetworking GET /pathParse into NSDictionary Server Return NSData[[AFHTTPClient sharedClient] getPath:@”path” parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) { // handle success } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // handle failure }];
  6. 6. Loading the ObjectCBPost *post = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:self.managedObjectContext];post.text = JSON[@”text”];//...[self.managedObjectContext save:&error];
  7. 7. Core Data• A System for Managing Data • It creates an “abstract” set of entities describing your app’s data model • It includes tools for persistence• Using it is an intermediate-level topic and has a lot of features, so we can not cover it in depth.
  8. 8. Core Data• For these types of web service apps, Core Data is mainly used for persistence, like a cache.• It allows the screens to have data, even when the app first launches or there is no network connection.
  9. 9. How It Works?• You have a model which contains “entities” in an Object Graph• These “entities” map to objects (NSManagedObjects)• The objects are used and connected together in a “context” (NSManagedObjectContext)• The context has an associated “persistent store coordinator” (NSPersistentStore). When the context is saved, the store coordinator writes to the disk.
  10. 10. Challenges• You should not use NSManagedObjectContexts on more than one thread (thread confinement).• Reading from a network is slow. Writing to the disk is slow. If possible, you do not want to do these things on the main thread.• But you do want to use NSManagedObjects on the main thread for UI.
  11. 11. Challenges• The main challenge of using Core Data has been figuring out how to create NSManagedObjects from a background and use them on various threads for displaying UI and saving to the disk.
  12. 12. Basic Answer Persistent Parent Child Store Context Context Coordinator Private Queue Main Queue• Before iOS 5, there was a method which used NSNotifications.• Since iOS 5, NSManagedObjectContexts can have both concurrency types (confinement, private, main) and parents. Children can pull the contents from their parent when they are created (but changes to the child do not propagate upwards automatically).• RestKit, the tool we are using, uses an NSManagedObjectContext in a private queue to write to the disk. It has a child context with a main queue type to interact with the main queue. It uses (short-lived) contexts to create the NSManagedObjects from the JSON objects.
  13. 13. New Advances• AFIncrementalStore• RestKit
  14. 14. AFIncrementalStore• Written by the author of AFNetworking• Uses a recent, more obscure feature of Core Data called NSIncrementalStore.• It is interesting because it allows you access the whole stack from Core Data.• I am worried that it is too closely tied to Core Data to be practical.
  15. 15. RestKit• More mature (but somewhat often rewritten)• More or less a consolidation of the workflow I described above.• Now uses AFNetworking under the hood.• Maybe has too many features(?). There are multiple ways to do the same thing and it was not always clear which was preferred.
  16. 16. RestKit1.Tell it about your Core Data model. It sets up you persistent store and contexts for you.2.Tell it what your various REST endpoints are on the server.3.Tell it how to take the JSON and map it to your Core Data entities.
  17. 17. RKManagedObjectStore_managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:self.managedObjectModel];[_managedObjectStore createPersistentStoreCoordinator];NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"CommunityBoard.sqlite"];NSError *error = nil;NSPersistentStore *persistentStore = [_managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];[_managedObjectStore createManagedObjectContexts];
  18. 18. RKEntityMappingRKEntityMapping *communityResponseMapping = [RKEntityMapping mappingForEntityForName:@"Community" inManagedObjectStore:self.managedObjectStore];communityResponseMapping.identificationAttributes = @[ @"communityId" ];[communityResponseMapping addAttributeMappingsFromDictionary:@{ @"id": @"communityId", @"created_at": @"createdAt", @"post_count": @"postCount"}];[communityResponseMapping addAttributeMappingsFromArray:@[@"name"]];
  19. 19. RKResponseDescriptorRKResponseDescriptor *communityResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:communityResponseMapping pathPattern:[CBAPI communitiesPath] keyPath:@"communities" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];[self addResponseDescriptor:communityResponseDescriptor];
  20. 20. Also, Authentication• Setting up OAuth is not difficult. There are libraries, such as AFOAuth2Client, which we use.• You will need an application id and secret bundled with your app.• You should save the OAuth token you receive on the User’s Keychain.• AFOAuthCredential (which comes with AFOAuth2Client) does that for you.
  21. 21. Example AFOAuth2Client *oauthClient = [AFOAuth2Client clientWithBaseURL:baseURL clientID:applicationID secret:secret];[oauthClient authenticateUsingOAuthWithPath:@”/oauth/token” username:username password:password scope:nil success:^(AFOAuthCredential *credential){ [AFOAuthCredential storeCredential:credential withIdentifier:CBCredentialIdentifier]; } failure:^(NSError *error){ // Handle Error }];