MPD2011 | Сергей Клюев "RESTfull iOS with RestKit"

1,800 views
1,695 views

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,800
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

MPD2011 | Сергей Клюев "RESTfull iOS with RestKit"

  1. 1. RESTful iOS with RestKit Taras Kalapun Sergey Kluev
  2. 2. What is RestKit? 2
  3. 3. 3
  4. 4. 4
  5. 5. RestKit Architecture • Network Layer • Object Mapping • Core Data • Pluggable parsing layer • Integration Points 5
  6. 6. Network Layer 6
  7. 7. Key Concepts• RKClient - Your user agent• Base URLs and Resource Paths• RKRequest & RKResponse - The HTTP lifecycle• RKRequestQueue - A lightweight queue implementation• RKParams - Multi-part MIME requests• Reachability - Detecting offline/online status 7
  8. 8. RKClient• Sending Asynchronous Requests1 – get:delegate:2 – get:queryParams:delegate:3 – post:params:delegate:4 – put:params:delegate:5 – delete:delegate: 8
  9. 9. Initializing RKClient- (void)initRKClient {! // Initialize with a Base URL! RKClient* client = [RKClient clientWithBaseURL:@"http://restkit.org"];!! // Setup HTTP AUTH! client.username = @"restkit";! client.password = @"rocks";!! // Set an app-wide API key HTTP header! [client setValue:@"123456" forHTTPHeaderField:@"X-RESTKIT-API-KEY"];!! // The first initialized RKClient becomes! // the sharedClient instance! [[RKClient sharedClient] isNetworkAvailable];} 9
  10. 10. Sending Requests- (void)sendRequest {! // Send an HTTP GET request to http://restkit.org/contacts! [[RKClient sharedClient] get:@"/contacts" delegate:self];}// RKRequestDelegate methods- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response {! NSLog(@"Yay! We Got a response");}- (void)request:(RKRequest*)request didFailLoadWithError:(NSError*)error {! NSLog(@"Oh no! Error: %@", [error localizedDescription]);} 10
  11. 11. Processing Responses- (void)sendRequest {! // Send an HTTP GET request to http://restkit.org/contacts! [[RKClient sharedClient] get:@"/contacts" delegate:self];}- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response{! NSLog(@"Request Headers: %@", [response allHeaderFields]);! NSLog(@"Cookies: %@", [response cookies])!! if ([response isSuccessful]) {! ! // Response status was 200..299! ! if ([response isCreated] && [response isJSON]) {! ! ! // Looks like we have a 201 response of type application/json! ! ! NSLog(@"The JSON is %@", [response bodyAsJSON]);! ! }! } else if ([response isError]) {! ! // Response status was either 400..499 or 500..599! ! NSLog(@"HTTP error, status Code: %@", [responselocalizedStatusCodeString]);! }} 11
  12. 12. Requests with Parameters- (void)sendRequestWithParams {! // Simple params! NSDictionary* paramsDictionary = [NSDictionarydictionaryWithObjectsAndKeys:! ! ! ! ! ! ! ! ! @"User", @"name",! ! ! ! ! ! ! ! ! @"Ciklum", @"company", nil];! [[RKClient sharedClient] post:@"/contacts" params:paramsDictionarydelegate:self];!! // Multi-part params via RKParams!! RKParams* params = [RKParams paramsWithDictionary:paramsDictionary];! NSData* imageData = UIImagePNGRepresentation([UIImageimageNamed:@"picture.jpg"]);! [params setData:imageData MIMEType:@"image/png" forParam:@"photo"];! [params setFile:@"bio.txt" forParam:@"attachment"];! [[RKClient sharedClient] post:@"/contacts" params:params delegate:self];} 12
  13. 13. Reachability- (void)demoReachability {! // Check if the network is available! [[RKClient sharedClient] isNetworkAvailable];!! // Register for changes in network availability! NSNotificationCenter* center = [NSNotificationCenter defaultCenter];! [center addObserver:self selector:@selector(reachabilityDidChange:)name:RKReachabilityStateChangedNotification object:nil];}- (void)reachabilityDidChange:(NSNotification*)notification {! RKReachabilityObserver* observer = (RKReachabilityObserver*)[notification object];! RKReachabilityNetworkStatus status = [observer networkStatus];! if (RKReachabilityNotReachable == status) {! ! NSLog(@"No network access!");! } else if (RKReachabilityReachableViaWiFi == status) {! ! NSLog(@"Online via WiFi!");! } else if (RKReachabilityReachableViaWWAN == status) {! ! NSLog(@"Online via Edge or 3G!");! }} 13
  14. 14. Object Mapping 2.0 14
  15. 15. Modeling a RESTful Service "user": { "id":31337, "name":"Blake Watters", "screen_name":"Blake Watters" } @interface RKTUser : NSObject @property (nonatomic, retain) NSNumber* userID; @property (nonatomic, retain) NSString* name; @property (nonatomic, retain) NSString* screenName; @end 15
  16. 16. "created_at":"Sat Mar 05 13:39:09 +0000 2011","favorited":false,"id":44029179364253700,"in_reply_to_screen_name":"JustJenFelice","text":"@JustJenFelice Be sure to join the Google Group andreach out if you need any support!","user":{ "id":208727870, "name":"RestKit", "screen_name":"RestKit", } 16
  17. 17. Initializing the Object Mapping 17
  18. 18. // Init RestKitRKObjectManager* objectManager = [RKObjectManagerobjectManagerWithBaseURL:@"http://twitter.com"];// Setup our object mappingsRKObjectMapping* userMapping = [RKObjectMapping mappingForClass:[RKTUser class]];[userMapping mapKeyPath:@"id" toAttribute:@"userID"];[userMapping mapKeyPath:@"screen_name" toAttribute:@"screenName"];[userMapping mapAttributes:@"name", nil]; 18
  19. 19. // Setup our object mappingsRKObjectMapping* statusMapping = [RKObjectMapping mappingForClass:[RKTStatus class]];[statusMapping mapKeyPathsToAttributes:@"id", @"statusID", @"created_at", @"createdAt", @"text", @"text", @"url", @"urlString", @"in_reply_to_screen_name", @"inReplyToScreenName", @"favorited", @"isFavorited", nil];[statusMapping mapRelationship:@"user" withObjectMapping:userMapping];// Update date format so that we can parse Twitter dates properly// Wed Sep 29 15:31:08 +0000 2010[statusMapping.dateFormatStrings addObject:@"E MMM d HH:mm:ss Z y"];// Register our mappings with the provider[objectManager.mappingProvider setObjectMapping:userMappingforKeyPath:@"user"];[objectManager.mappingProvider setObjectMapping:statusMappingforKeyPath:@"status"]; 19
  20. 20. Loading Remote Objects- (void)loadTimeline { // Load the object model via RestKit! RKObjectManager* objectManager = [RKObjectManager sharedManager]; RKObjectMapping* statusMapping = nil; // Twitter returns statuses as a naked array in JSON, so we instructthe loader to user the appropriate object mapping if ([objectManager.acceptMIMEType isEqualToString:RKMIMETypeJSON]) { statusMapping = [objectManager.mappingProviderobjectMappingForKeyPath:@"status"]; } [objectManager loadObjectsAtResourcePath:@"/status/user_timeline/RestKit" objectMapping:statusMapping delegate:self];}- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {! NSLog(@"Loaded statuses: %@", objects);} 20
  21. 21. Configuring the Router- (void)configureRouter {! [objectManager.router routeClass:[Contact class] toResourcePath:@"/contacts/(contactID)"];! [objectManager.router routeClass:[Contact class] toResourcePath:@"/contacts"forMethod:RKRequestMethodPOST];} 21
  22. 22. RESTful Object Manipulation// Create a new Contact- (void)createObject {! Contact* contact = [Contact new];! contact.name = @"RestKit User";! contact.email = @"user@restkit.org";!! // POST to /contacts! [[RKObjectManager sharedManager] postObject:contact delegate:self];}// Edit Contact with ID 12345- (void)editObject {! Contact* contact = [Contact new];! contact.contactID = [NSNumber numberWithInt:12345];! contact.name = @"New Name";!! // POST to /contacts/12345! [[RKObjectManager sharedManager] putObject:contact delegate:self];}// Delete Contact with ID 321- (void)deleteObject {! Contact* contact = [Contact new];! contact.contactID = [NSNumber numberWithInt:321];!! // DELETE to /contacts/321! [[RKObjectManager sharedManager] deleteObject:contact delegate:self];!} 22
  23. 23. Core Data 23
  24. 24. Configuring CoreData#import <RestKit/CoreData/CoreData.h>- (void)configureObjectStore { // Initialize the RestKit Object Manager RKObjectManager* objectManager = [RKObjectManagerobjectManagerWithBaseURL:@"http://restkit.org"];! // Initialize object store // We are using the Core Data support, so we have initialized a managedobject store backed // with a SQLite database. objectManager.objectStore = [RKManagedObjectStoreobjectStoreWithStoreFilename:@"Contacts.sqlite"];} 24
  25. 25. MappingRKManagedObjectMapping* userMapping = [RKManagedObjectMappingmappingForEntityWithName:@"RKTUser"];userMapping.primaryKeyAttribute = @"userID";[userMapping mapKeyPath:@"id" toAttribute:@"userID"];[userMapping mapKeyPath:@"screen_name" toAttribute:@"screenName"];[userMapping mapAttributes:@"name", nil]; 25
  26. 26. Working with Core Data// Adapted from https://github.com/magicalpanda/MagicalRecord// Get all the ContactsNSArray* contacts = [Contact allObjects];!// Count the ContactsNSError* error = nil;NSUInteger count = [Contact count:&error];!// Find Contact by primary keyNSNumber* contactID = [NSNumber numberWithInt:12345];Contact* somebody = [Contact objectWithPrimaryKeyValue:contactID];!// Find Contacts with criteriaNSPredicate* predicate = [NSPredicate predicateWithFormat:@"namecontains[cd] restkit"];NSArray* matches = [Contact objectsWithPredicate:predicate]; 26
  27. 27. Database SeedingNSString *seedDatabaseName = nil;NSString *databaseName = RKDefaultSeedDatabaseFileName;objectManager.objectStore = [RKManagedObjectStoreobjectStoreWithStoreFilename:databaseNameusingSeedDatabaseName:seedDatabaseName managedObjectModel:nildelegate:self];RKManagedObjectSeeder* seeder = [RKManagedObjectSeederobjectSeederWithObjectManager:objectManager];// Seed DB with instances of RKTStatus from a snapshot of the RestKitTwitter timeline[seeder seedObjectsFromFile:@"restkit.json"withObjectMapping:statusMapping];// Seed DB with RKTUser objects. The class will be inferred via elementregistration[seeder seedObjectsFromFiles:@"users.json", nil];// Finalize the seeding and output a helpful informational message[seeder finalizeSeedingAndExit]; 27
  28. 28. Pluggable parsing layer• JSON- SBJSON- NXJSON- YAJL- JSONKit• XML 28
  29. 29. // Adapted from https://github.com/magicalpanda/MagicalRecord// Get all the ContactsNSArray* contacts = [Contact allObjects];!// Count the ContactsNSError* error = nil;NSUInteger count = [Contact count:&error];!// Find Contact by primary keyNSNumber* contactID = [NSNumber numberWithInt:12345];Contact* somebody = [Contact objectWithPrimaryKeyValue:contactID];!// Find Contacts with criteriaNSPredicate* predicate = [NSPredicate predicateWithFormat:@"namecontains[cd] restkit"];NSArray* matches = [Contact objectsWithPredicate:predicate]; 29
  30. 30. Integration PointsThree20 Ruby on Rails 30
  31. 31. http://restkit.org/ http://twitter.com/restkithttp://github.com/RestKit/RestKit
  32. 32. ?

×