Overcoat is an AFNetworking extension that makes it extremely simple for developers to use Mantle model objects with a REST client.
If you need to learn more about Mantle, we recommend these resources:
We will use the iTunes Search API to create a class that searches for books in the iTunes Store.
First, lets create a book model using Mantle:
@interface TGRBook : MTLModel <MTLJSONSerializing>
@property (copy, nonatomic, readonly) NSString *author;
@property (copy, nonatomic, readonly) NSString *overview;
@property (copy, nonatomic, readonly) NSArray *genres;
@property (copy, nonatomic, readonly) NSDate *releaseDate;
@property (copy, nonatomic, readonly) NSNumber *identifier;
@property (copy, nonatomic, readonly) NSString *title;
@property (copy, nonatomic, readonly) NSURL *coverURL;
@endThe iTunes Search API will return a JSON with the following format:
{
"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",
...We need to tell our model how to map JSON keys to properties. We can do that by implementing the MTLJSONSerializing protocol:
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{
@"author": @"artistName",
@"overview": @"description",
@"identifier": @"trackId",
@"title": @"trackName",
@"coverURL": @"artworkUrl100"
};
}
+ (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];
}Once we have the model, we can create an OVCClient subclass that will implement the search method:
@interface TGRBookCatalog : OVCClient
- (void)searchBooksWithTerm:(NSString *)term completion:(void (^)(NSArray *results, NSError *error))block;
@endThe implementation of TGRBookCatalog is pretty simple:
- (id)init {
return [super initWithBaseURL:[NSURL URLWithString:@"https://itunes.apple.com"]];
}
- (void)searchBooksWithTerm:(NSString *)term completion:(void (^)(NSArray *results, NSError *error))block {
NSDictionary *parameters = @{
@"term": term,
@"entity": @"ebook"
};
[self GET:@"search" parameters:parameters resultClass:TGRBook.class resultKeyPath:@"results" completion:^(AFHTTPRequestOperation *operation, id responseObject, NSError *error) {
block(responseObject, error);
}];
}OVCClient provides methods to make GET, POST and PUT requests specifiying how to map the response to a model object. In this case we are telling OVCClient that we want TGRBook objects that can be found under the key results in the JSON response.
Now we can use TGRBookCatalog to launch a search in iTunes and get an array of TGRBook objects:
[self.bookCatalog searchBooksWithTerm:@"the sandman" completionBlock:^(NSArray *results, NSError *error) {
if (error == nil) {
NSLog(@"results: %@", results); // results is an array of TGRBook instances!
}
}];You can find the complete example (including TGRBook serialization to a Core Data entity) here.
OVCClient can authenticate API requests using an ACAccount object on supported social networking services (currently Twitter, Facebook, and Sina Weibo).
For example, here is how we could lookup for Twitter users (provided that we have an Twitter account).
@interface TwitterUser : MTLModel <MTLJSONSerializing>
@property (copy, nonatomic, readonly) NSString *identifier;
@property (copy, nonatomic, readonly) NSString *name;
@property (copy, nonatomic, readonly) NSString *screenName;
@end@implementation TwitterUser
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{
@"identifier": @"id_str",
@"screenName": @"screen_name"
};
}
@endOVCClient *client = [OVCClient clientWithBaseURL:[NSURL URLWithString:@"https://api.twitter.com/1.1"]
account:myAccount];
NSDictionary *parameters = @{
@"screen_name": @"twitterapi,twitter"
};
[client GET:@"users/lookup.json" parameters:parameters resultClass:TwitterUser.class resultKeyPath:nil completion:^(AFHTTPRequestOperation *operation, NSArray *users, NSError *error) {
if (!error) {
for (TwitterUser *user in users) {
NSLog(@"name: %@ screenName: %@", user.name, user.screenName);
}
}
}];ReadingList is a fairly complete iOS sample application that shows how to use Overcoat.
Guillermo Gonzalez
@gonzalezreal
Overcoat is available under the MIT license. See LICENSE.md.