Your SlideShare is downloading. ×
0
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Better Web Clients with Mantle and AFNetworking
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Better Web Clients with Mantle and AFNetworking

4,017

Published on

NSCoder Madrid: Talk about how to use Mantle and AFNetworking together. You can find the sample code here https://github.com/gonzalezreal/ReadingList

NSCoder Madrid: Talk about how to use Mantle and AFNetworking together. You can find the sample code here https://github.com/gonzalezreal/ReadingList

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

No Downloads
Views
Total Views
4,017
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
63
Comments
0
Likes
12
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Better Web Clients with Mantle & AFNetworking
  • 2. Guillermo González @gonzalezreal
  • 3. Mantle Model framework for Cocoa and Cocoa Touch
  • 4. https://github.com/github/Mantle
  • 5. Makes it easy to write a simple model layer
  • 6. Gets rid of boilerplate code
  • 7. Gets rid of boilerplate code -hash
  • 8. Gets rid of boilerplate code -hash -isEqual:
  • 9. Gets rid of boilerplate code -hash -isEqual: NSCopying
  • 10. Gets rid of boilerplate code -hash -isEqual: NSCopying NSCoding
  • 11. Example: Book Model @interface TGRBook : MTLModel ! @property @property @property @property @property @property @property ! @end (copy, (copy, (copy, (copy, (copy, (copy, (copy, nonatomic, nonatomic, nonatomic, nonatomic, nonatomic, nonatomic, nonatomic, readonly) readonly) readonly) readonly) readonly) readonly) readonly) NSString *author; NSString *overview; NSArray *genres; NSDate *releaseDate; NSNumber *identifier; NSString *title; NSURL *coverURL;
  • 12. Example: Book Model @interface TGRBook : MTLModel ! @property @property @property @property @property @property @property (copy, (copy, (copy, (copy, (copy, (copy, (copy, nonatomic, nonatomic, nonatomic, nonatomic, nonatomic, nonatomic, nonatomic, readonly) readonly) readonly) readonly) readonly) readonly) readonly) NSString *author; NSString *overview; NSArray *genres; NSDate *releaseDate; NSNumber *identifier; NSString *title; NSURL *coverURL; ! @end Prefer immutable model objects
  • 13. NSError *error = nil; TGRBook *book = [TGRBook modelWithDictionary:@{ @"title" : @"The Sandman", @"author" : @"Neil Gaiman", @"genres" : @[@"Graphic Novels", @"Fantasy"], ... } error:&error];
  • 14. NSError *error = nil; TGRBook *book = [TGRBook modelWithDictionary:@{ @"title" : @"The Sandman", @"author" : @"Neil Gaiman", @"genres" : @[@"Graphic Novels", @"Fantasy"], ... } error:&error]; TGRBook *anotherBook = [book copy];
  • 15. NSError *error = nil; TGRBook *book = [TGRBook modelWithDictionary:@{ @"title" : @"The Sandman", @"author" : @"Neil Gaiman", @"genres" : @[@"Graphic Novels", @"Fantasy"], ... } error:&error]; TGRBook *anotherBook = [book copy]; [NSKeyedArchiver archiveRootObject:book toFile:@"my_file"];
  • 16. NSError *error = nil; TGRBook *book = [TGRBook modelWithDictionary:@{ @"title" : @"The Sandman", @"author" : @"Neil Gaiman", @"genres" : @[@"Graphic Novels", @"Fantasy"], ... } error:&error]; TGRBook *anotherBook = [book copy]; [NSKeyedArchiver archiveRootObject:book toFile:@"my_file"]; TGRBook *b = [NSKeyedUnarchiver unarchiveObjectWithFile:@"my_file"];
  • 17. (lldb) po book
  • 18. (lldb) po book $0 = 0x0a349050 <TGRBook: 0xa349050> { author = "Neil Gaiman, Sam Keith & Mike Dringenberg"; coverURL = "http://a4.mzstatic.com/us/r30/Publication/..."; genres = ( "Graphic Novels", Books, "Comics & Graphic Novels" ); identifier = 554016043; overview = "<p>NEW YORK TIMES bestselling author Neil Gaiman's..."; releaseDate = "2012-08-21 05:00:00 +0000"; title = "The Sandman, Vol. 1: Preludes & Nocturnes (New Edition)"; }
  • 19. All this just by subclassing MTLModel
  • 20. Our Book Model could have a JSON representation
  • 21. Our Book Model could have a JSON representation { ... "artistName": "Neil Gaiman, Sam Keith & Mike Dringenberg", "description": "<p>NEW YORK TIMES bestselling author...", "genres": ["Graphic Novels", "Books", "Comics & Graphic Novels"], "releaseDate": "2012-08-21T07:00:00Z", "trackId": 554016043, "trackName": "The Sandman, Vol. 1: Preludes & Nocturnes (New Edition)", "artworkUrl100": "http://a4.mzstatic.com/us/r30/Publication/...", ... }
  • 22. Our Book Model could have a JSON representation { ... "artistName": "Neil Gaiman, Sam Keith & Mike Dringenberg", "description": "<p>NEW YORK TIMES bestselling author...", "genres": ["Graphic Novels", "Books", "Comics & Graphic Novels"], "releaseDate": "2012-08-21T07:00:00Z", "trackId": 554016043, "trackName": "The Sandman, Vol. 1: Preludes & Nocturnes (New Edition)", "artworkUrl100": "http://a4.mzstatic.com/us/r30/Publication/...", ... } This is how iTunes represents media (including books)
  • 23. Our Book Model could have a JSON representation { ... "artistName": "Neil Gaiman, Sam Keith & Mike Dringenberg", "description": "<p>NEW YORK TIMES bestselling author...", "genres": ["Graphic Novels", "Books", "Comics & Graphic Novels"], "releaseDate": "2012-08-21T07:00:00Z", "trackId": 554016043, "trackName": "The Sandman, Vol. 1: Preludes & Nocturnes (New Edition)", "artworkUrl100": "http://a4.mzstatic.com/us/r30/Publication/...", ... } This is how iTunes represents media (including books) See http://www.apple.com/itunes/affiliates/resources/ documentation/itunes-store-web-service-search-api.html
  • 24. MTLJSONSerializing protocol @interface TGRBook : MTLModel <MTLJSONSerializing>
  • 25. MTLJSONSerializing protocol @interface TGRBook : MTLModel <MTLJSONSerializing> Specify how to map properties to JSON keypaths
  • 26. MTLJSONSerializing protocol @interface TGRBook : MTLModel <MTLJSONSerializing> Specify how to map properties to JSON keypaths Specify how to convert a JSON value to a property key
  • 27. + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"author" : @"artistName", @"overview" : @"description", @"identifier" : @"trackId", @"title" : @"trackName", @"coverURL" : @"artworkUrl100" }; }
  • 28. + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"author" : @"artistName", @"overview" : @"description", @"identifier" : @"trackId", @"title" : @"trackName", @"coverURL" : @"artworkUrl100" }; } Only properties with a corresponding ivar
  • 29. + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"author" : @"artistName", @"overview" : @"description", @"identifier" : @"trackId", @"title" : @"trackName", @"coverURL" : @"artworkUrl100" }; } Only properties with a corresponding ivar Property keys not present in the dictionary are assumed to match the JSON
  • 30. + (NSValueTransformer *)releaseDateJSONTransformer { return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) { return [self.dateFormatter dateFromString:str]; } reverseBlock:^(NSDate *date) { return [self.dateFormatter stringFromDate:date]; }]; } ! + (NSValueTransformer *)coverURLJSONTransformer { return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName]; }
  • 31. + (NSValueTransformer *)releaseDateJSONTransformer { return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) { return [self.dateFormatter dateFromString:str]; } reverseBlock:^(NSDate *date) { return [self.dateFormatter stringFromDate:date]; }]; } ! + (NSValueTransformer *)coverURLJSONTransformer { return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName]; } +<key>JSONTransformer methods
  • 32. + (NSValueTransformer *)releaseDateJSONTransformer { return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) { return [self.dateFormatter dateFromString:str]; } reverseBlock:^(NSDate *date) { return [self.dateFormatter stringFromDate:date]; }]; } ! + (NSValueTransformer *)coverURLJSONTransformer { return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName]; } +<key>JSONTransformer MTLValueTransformer methods is a block-based value transformer
  • 33. + (NSValueTransformer *)releaseDateJSONTransformer { return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) { return [self.dateFormatter dateFromString:str]; } reverseBlock:^(NSDate *date) { return [self.dateFormatter stringFromDate:date]; }]; } ! + (NSValueTransformer *)coverURLJSONTransformer { return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName]; } +<key>JSONTransformer MTLValueTransformer methods is a block-based value transformer Predefined transformers: MTLURLValueTransformerName and MTLBooleanValueTransformerName
  • 34. Mapping JSON child objects
  • 35. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end
  • 36. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end + (NSValueTransformer *)purchasedBooksJSONTransformer {
  • 37. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end + (NSValueTransformer *)purchasedBooksJSONTransformer { return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class];
  • 38. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end + (NSValueTransformer *)purchasedBooksJSONTransformer { return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; }
  • 39. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end + (NSValueTransformer *)purchasedBooksJSONTransformer { return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; }
  • 40. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end + (NSValueTransformer *)purchasedBooksJSONTransformer { return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; } + (NSValueTransformer *)nowReadingJSONTransformer {
  • 41. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end + (NSValueTransformer *)purchasedBooksJSONTransformer { return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; } + (NSValueTransformer *)nowReadingJSONTransformer { return [NSValueTransformer mtl_JSONDictionaryTransformerWithModelClass:TGRBook.class];
  • 42. MTLJSONAdapter TGRBook *book = [MTLJSONAdapter modelOfClass:TGRBook.class fromJSONDictionary:JSONDictionary error:&error]; ! ! NSDictionary *dictionary = [MTLJSONAdapter JSONDictionaryFromModel:book];
  • 43. Do we still need Core Data?
  • 44. Do we still need Core Data? Of course!
  • 45. Do we still need Core Data? Of course! Memory efficiency with large datasets
  • 46. Do we still need Core Data? Of course! Memory efficiency with large datasets NSFetchRequest is cool!
  • 47. Do we still need Core Data? Of course! Memory efficiency with large datasets NSFetchRequest is cool! Mantle and Core Data can work together
  • 48. An entity for our Book Model
  • 49. MTLManagedObjectSerializing protocol @interface TGRBook : MTLModel <MTLManagedObjectSerializing>
  • 50. MTLManagedObjectSerializing protocol @interface TGRBook : MTLModel <MTLManagedObjectSerializing> Specify the entity name
  • 51. MTLManagedObjectSerializing protocol @interface TGRBook : MTLModel <MTLManagedObjectSerializing> Specify the entity name Specify how to map properties to managed object attributes
  • 52. MTLManagedObjectSerializing protocol @interface TGRBook : MTLModel <MTLManagedObjectSerializing> Specify the entity name Specify how to map properties to managed object attributes Specify how to convert a managed object attribute value to a property key
  • 53. + (NSString *)managedObjectEntityName { return @"Book"; } ! + (NSDictionary *)managedObjectKeysByPropertyKey { return @{ @"coverURL" : @"coverLink" }; } ! + (NSValueTransformer *)coverURLEntityAttributeTransformer { return [[NSValueTransformer valueTransformerForName:MTLURLValueTransformerName] mtl_invertedTransformer]; }
  • 54. MTLManagedObjectAdapter NSManagedObject *managedBook = [MTLManagedObjectAdapter managedObjectFromModel:book insertingIntoContext:moc error:&error]; ! ! ! TGRBook *book = [MTLManagedObjectAdapter modelOfClass:TGRBook.class fromManagedObject:object error:&error];
  • 55. A delightful iOS and OS X networking framework Built on top of Foundation technologies Easy to use block-based API Amazing community of developers Used by some of the most popular apps on iOS and OSX https://github.com/AFNetworking/AFNetworking
  • 56. Example: Search books NSURL *url = [NSURL URLWithString:@"https://itunes.apple.com"]; AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:url]; ! [client getPath:@"search" parameters:@{ @"term" : @"the sandman", @"entity" : @"ebook" } success:^(AFHTTPRequestOperation *operation, id JSONResponse) { NSLog(@"Search results: %@", JSONResponse); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { ... }];
  • 57. JSON Response { "resultCount": 50, "results": [{ "artistId": 3603584, "artistName": "Neil Gaiman, Sam Kieth & Mike Dringenberg", "kind": "ebook", "price": 1.99, "description": "<p>The first issue of the first volume...", "currency": "USD", "genres": ["Graphic Novels", "Books", "Comics & Graphic Novels"], "genreIds": ["10015", "38", "9026"], "releaseDate": "2013-05-01T07:00:00Z", "trackId": 642469670, "trackName": "Sandman #1", ...
  • 58. Let’s add a Mantle [client getPath:@"search" parameters:@{ @"term" : @"Neil Gaiman", @"entity" : @"ebook" } success:^(AFHTTPRequestOperation *operation, NSDictionary *JSONResponse) { ! ! NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results]; NSLog(@"Books: %@", books); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { ... }];
  • 59. Let’s add a Mantle [client getPath:@"search" parameters:@{ @"term" : @"Neil Gaiman", @"entity" : @"ebook" } success:^(AFHTTPRequestOperation *operation, NSDictionary *JSONResponse) { ! ! NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results]; NSLog(@"Books: %@", books); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { ... }];
  • 60. NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results];
  • 61. NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results]; Mapping can potentially take time
  • 62. NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results]; Mapping can potentially take time It should be done in a background queue
  • 63. NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results]; Mapping can potentially take time It should be done in a background queue Boilerplate code again!
  • 64. Overcoat The perfect accessory for Mantle Makes it dead simple to use Mantle model objects with a RESTful client AFNetworking extension https://github.com/gonzalezreal/Overcoat
  • 65. Overcoat OVCRequestOperation OVCClient AFJSONRequestOperation AFHTTPClient AFHTTPRequestOperation OVCQuery OVCSocialClien
  • 66. Overcoat 0.x OVCQuery *query = [OVCQuery queryWithMethod:OVCQueryMethodGet path:@"search" parameters:@{ @"term" : term, @"entity" : @"ebook" } modelClass:TGRBook.class objectKeyPath:@"results"]; ! [client executeQuery:query completionBlock:^(OVCRequestOperation *operation, NSArray *books, NSError *error) { NSLog(@"Books: %@", books); }];
  • 67. Overcoat 1.0
  • 68. Overcoat 1.0 NSDictionary *parameters = @{ @"term" : term, @"entity" : @"ebook" }; ! [client GET:@"search" parameters:parameters resultClass:TGRBook.class resultKeyPath:@"results" completion:^(AFHTTPRequestOperation *operation, NSArray *books, NSError *error) { NSLog(@"Books: %@", books); }];
  • 69. Overcoat 1.0 NSDictionary *parameters = @{ @"term" : term, @"entity" : @"ebook" }; ! [client GET:@"search" parameters:parameters resultClass:TGRBook.class resultKeyPath:@"results" completion:^(AFHTTPRequestOperation *operation, NSArray *books, NSError *error) { NSLog(@"Books: %@", books); }]; Coming soon...
  • 70. Overcoat Server API requests are defined by OVCQuery objects. HTTP method, path, parameters, model class, multipart data, etc. Maps JSON into model(s) In a private background queue
  • 71. Overcoat Pull Requests are welcome!
  • 72. Demo Application https://github.com/gonzalezreal/ReadingList
  • 73. Thanks!

×