SlideShare uma empresa Scribd logo
1 de 74
Baixar para ler offline
Better Web Clients with
Mantle & AFNetworking
Guillermo González
@gonzalezreal
Mantle
Model framework for Cocoa and Cocoa Touch
https://github.com/github/Mantle
Makes it easy to write a
simple model layer
Gets rid of boilerplate code
Gets rid of boilerplate code
-hash
Gets rid of boilerplate code
-hash
-isEqual:
Gets rid of boilerplate code
-hash
-isEqual:
NSCopying
Gets rid of boilerplate code
-hash
-isEqual:
NSCopying
NSCoding
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;
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
NSError *error = nil;
TGRBook *book = [TGRBook modelWithDictionary:@{
@"title" : @"The Sandman",
@"author" : @"Neil Gaiman",
@"genres" : @[@"Graphic Novels", @"Fantasy"],
...
} error:&error];
NSError *error = nil;
TGRBook *book = [TGRBook modelWithDictionary:@{
@"title" : @"The Sandman",
@"author" : @"Neil Gaiman",
@"genres" : @[@"Graphic Novels", @"Fantasy"],
...
} error:&error];

TGRBook *anotherBook = [book copy];
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"];
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"];
(lldb) po book
(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)";
}
All this just by subclassing MTLModel
Our Book Model could
have a JSON representation
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/...",
...
}
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)
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
MTLJSONSerializing protocol
@interface TGRBook : MTLModel <MTLJSONSerializing>
MTLJSONSerializing protocol
@interface TGRBook : MTLModel <MTLJSONSerializing>

Specify how to map properties to JSON
keypaths
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
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{
@"author" : @"artistName",
@"overview" : @"description",
@"identifier" : @"trackId",
@"title" : @"trackName",
@"coverURL" : @"artworkUrl100"
};
}
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{
@"author" : @"artistName",
@"overview" : @"description",
@"identifier" : @"trackId",
@"title" : @"trackName",
@"coverURL" : @"artworkUrl100"
};
}

Only properties with a corresponding ivar
+ (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
+ (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];
}
+ (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
+ (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
+ (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
Mapping JSON child objects
Mapping JSON child objects
@interface TGRUser : MTLModel <MTLJSONSerializing>

!

@property (copy, nonatomic, readonly) NSArray *purchasedBooks;
@property (copy, nonatomic, readonly) TGRBook *nowReading;

!

@end
Mapping JSON child objects
@interface TGRUser : MTLModel <MTLJSONSerializing>

!

@property (copy, nonatomic, readonly) NSArray *purchasedBooks;
@property (copy, nonatomic, readonly) TGRBook *nowReading;

!

@end
+ (NSValueTransformer *)purchasedBooksJSONTransformer {
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];
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];
}
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];
}
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 {
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];
MTLJSONAdapter
TGRBook *book = [MTLJSONAdapter modelOfClass:TGRBook.class
fromJSONDictionary:JSONDictionary
error:&error];

!
!

NSDictionary *dictionary = [MTLJSONAdapter JSONDictionaryFromModel:book];
Do we still need Core Data?
Do we still need Core Data?
Of course!
Do we still need Core Data?
Of course!
Memory efficiency with large datasets
Do we still need Core Data?
Of course!
Memory efficiency with large datasets
NSFetchRequest is cool!
Do we still need Core Data?
Of course!
Memory efficiency with large datasets
NSFetchRequest is cool!
Mantle and Core Data can work together
An entity for our Book Model
MTLManagedObjectSerializing protocol
@interface TGRBook : MTLModel <MTLManagedObjectSerializing>
MTLManagedObjectSerializing protocol
@interface TGRBook : MTLModel <MTLManagedObjectSerializing>

Specify the entity name
MTLManagedObjectSerializing protocol
@interface TGRBook : MTLModel <MTLManagedObjectSerializing>

Specify the entity name
Specify how to map properties to managed
object attributes
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
+ (NSString *)managedObjectEntityName {
return @"Book";
}

!

+ (NSDictionary *)managedObjectKeysByPropertyKey {
return @{
@"coverURL" : @"coverLink"
};
}

!

+ (NSValueTransformer *)coverURLEntityAttributeTransformer {
return [[NSValueTransformer valueTransformerForName:MTLURLValueTransformerName]
mtl_invertedTransformer];
}
MTLManagedObjectAdapter
NSManagedObject *managedBook = [MTLManagedObjectAdapter managedObjectFromModel:book
insertingIntoContext:moc
error:&error];

!
!
!

TGRBook *book = [MTLManagedObjectAdapter modelOfClass:TGRBook.class
fromManagedObject:object
error:&error];
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
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) {
...
}];
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",
...
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) {
...
}];
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) {
...
}];
NSArray *results = JSONResponse[@"results"];
NSValueTransformer *transformer;
transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class];
NSArray *books = [transformer transformedValue:results];
NSArray *results = JSONResponse[@"results"];
NSValueTransformer *transformer;
transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class];
NSArray *books = [transformer transformedValue:results];

Mapping can potentially take time
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
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!
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
Overcoat
OVCRequestOperation
OVCClient
AFJSONRequestOperation
AFHTTPClient
AFHTTPRequestOperation

OVCQuery

OVCSocialClien
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);
}];
Overcoat 1.0
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);
}];
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...
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
Overcoat
Pull Requests are welcome!
Demo Application
https://github.com/gonzalezreal/ReadingList
Thanks!

Mais conteúdo relacionado

Mais procurados

Conceptos básicos. Seminario web 5: Introducción a Aggregation Framework
Conceptos básicos. Seminario web 5: Introducción a Aggregation FrameworkConceptos básicos. Seminario web 5: Introducción a Aggregation Framework
Conceptos básicos. Seminario web 5: Introducción a Aggregation FrameworkMongoDB
 
Agile Schema Design: An introduction to MongoDB
Agile Schema Design: An introduction to MongoDBAgile Schema Design: An introduction to MongoDB
Agile Schema Design: An introduction to MongoDBStennie Steneker
 
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB Europe 2016 - Debugging MongoDB PerformanceMongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB Europe 2016 - Debugging MongoDB PerformanceMongoDB
 
Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! aleks-f
 
Diagnostics & Debugging webinar
Diagnostics & Debugging webinarDiagnostics & Debugging webinar
Diagnostics & Debugging webinarMongoDB
 
Concept of BlockChain & Decentralized Application
Concept of BlockChain & Decentralized ApplicationConcept of BlockChain & Decentralized Application
Concept of BlockChain & Decentralized ApplicationSeiji Takahashi
 
はじめてのMongoDB
はじめてのMongoDBはじめてのMongoDB
はじめてのMongoDBTakahiro Inoue
 
C# Development (Sam Corder)
C# Development (Sam Corder)C# Development (Sam Corder)
C# Development (Sam Corder)MongoSF
 
ETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDBETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDBMongoDB
 
durability, durability, durability
durability, durability, durabilitydurability, durability, durability
durability, durability, durabilityMatthew Dennis
 
Back to Basics Webinar 3: Schema Design Thinking in Documents
 Back to Basics Webinar 3: Schema Design Thinking in Documents Back to Basics Webinar 3: Schema Design Thinking in Documents
Back to Basics Webinar 3: Schema Design Thinking in DocumentsMongoDB
 
Back to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation FrameworkBack to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation FrameworkMongoDB
 
Qtp+real time+test+script
Qtp+real time+test+scriptQtp+real time+test+script
Qtp+real time+test+scriptRamu Palanki
 
Monolith to Reactive Microservices
Monolith to Reactive MicroservicesMonolith to Reactive Microservices
Monolith to Reactive MicroservicesReactivesummit
 
Cassandra, Modeling and Availability at AMUG
Cassandra, Modeling and Availability at AMUGCassandra, Modeling and Availability at AMUG
Cassandra, Modeling and Availability at AMUGMatthew Dennis
 
JSON-(JavaScript Object Notation)
JSON-(JavaScript Object Notation)JSON-(JavaScript Object Notation)
JSON-(JavaScript Object Notation)Skillwise Group
 
The Ring programming language version 1.8 book - Part 46 of 202
The Ring programming language version 1.8 book - Part 46 of 202The Ring programming language version 1.8 book - Part 46 of 202
The Ring programming language version 1.8 book - Part 46 of 202Mahmoud Samir Fayed
 

Mais procurados (20)

Conceptos básicos. Seminario web 5: Introducción a Aggregation Framework
Conceptos básicos. Seminario web 5: Introducción a Aggregation FrameworkConceptos básicos. Seminario web 5: Introducción a Aggregation Framework
Conceptos básicos. Seminario web 5: Introducción a Aggregation Framework
 
Agile Schema Design: An introduction to MongoDB
Agile Schema Design: An introduction to MongoDBAgile Schema Design: An introduction to MongoDB
Agile Schema Design: An introduction to MongoDB
 
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB Europe 2016 - Debugging MongoDB PerformanceMongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB Europe 2016 - Debugging MongoDB Performance
 
Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! 
 
Diagnostics & Debugging webinar
Diagnostics & Debugging webinarDiagnostics & Debugging webinar
Diagnostics & Debugging webinar
 
Concept of BlockChain & Decentralized Application
Concept of BlockChain & Decentralized ApplicationConcept of BlockChain & Decentralized Application
Concept of BlockChain & Decentralized Application
 
はじめてのMongoDB
はじめてのMongoDBはじめてのMongoDB
はじめてのMongoDB
 
Esperwhispering
EsperwhisperingEsperwhispering
Esperwhispering
 
C# Development (Sam Corder)
C# Development (Sam Corder)C# Development (Sam Corder)
C# Development (Sam Corder)
 
Elastic search 검색
Elastic search 검색Elastic search 검색
Elastic search 검색
 
ETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDBETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDB
 
durability, durability, durability
durability, durability, durabilitydurability, durability, durability
durability, durability, durability
 
Back to Basics Webinar 3: Schema Design Thinking in Documents
 Back to Basics Webinar 3: Schema Design Thinking in Documents Back to Basics Webinar 3: Schema Design Thinking in Documents
Back to Basics Webinar 3: Schema Design Thinking in Documents
 
Back to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation FrameworkBack to Basics Webinar 5: Introduction to the Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation Framework
 
Qtp+real time+test+script
Qtp+real time+test+scriptQtp+real time+test+script
Qtp+real time+test+script
 
Monolith to Reactive Microservices
Monolith to Reactive MicroservicesMonolith to Reactive Microservices
Monolith to Reactive Microservices
 
Postgres demystified
Postgres demystifiedPostgres demystified
Postgres demystified
 
Cassandra, Modeling and Availability at AMUG
Cassandra, Modeling and Availability at AMUGCassandra, Modeling and Availability at AMUG
Cassandra, Modeling and Availability at AMUG
 
JSON-(JavaScript Object Notation)
JSON-(JavaScript Object Notation)JSON-(JavaScript Object Notation)
JSON-(JavaScript Object Notation)
 
The Ring programming language version 1.8 book - Part 46 of 202
The Ring programming language version 1.8 book - Part 46 of 202The Ring programming language version 1.8 book - Part 46 of 202
The Ring programming language version 1.8 book - Part 46 of 202
 

Semelhante a Better Web Clients with Mantle and AFNetworking

Introduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopIntroduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopSteven Francia
 
(Big) Data Serialization with Avro and Protobuf
(Big) Data Serialization with Avro and Protobuf(Big) Data Serialization with Avro and Protobuf
(Big) Data Serialization with Avro and ProtobufGuido Schmutz
 
Modernizes your objective C - Oliviero
Modernizes your objective C - OlivieroModernizes your objective C - Oliviero
Modernizes your objective C - OlivieroCodemotion
 
Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015StampedeCon
 
Aggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days MunichAggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days MunichNorberto Leite
 
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013PostgresOpen
 
PostgreSQL 9.3 and JSON - talk at PgOpen 2013
PostgreSQL 9.3 and JSON - talk at PgOpen 2013PostgreSQL 9.3 and JSON - talk at PgOpen 2013
PostgreSQL 9.3 and JSON - talk at PgOpen 2013Andrew Dunstan
 
Building Go Web Apps
Building Go Web AppsBuilding Go Web Apps
Building Go Web AppsMark
 
IT Days - Parse huge JSON files in a streaming way.pptx
IT Days - Parse huge JSON files in a streaming way.pptxIT Days - Parse huge JSON files in a streaming way.pptx
IT Days - Parse huge JSON files in a streaming way.pptxAndrei Negruti
 
Webinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev TeamsWebinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev TeamsMongoDB
 
The Ring programming language version 1.6 book - Part 25 of 189
The Ring programming language version 1.6 book - Part 25 of 189The Ring programming language version 1.6 book - Part 25 of 189
The Ring programming language version 1.6 book - Part 25 of 189Mahmoud Samir Fayed
 
Introduction to mongodb for bioinformatics
Introduction to mongodb for bioinformaticsIntroduction to mongodb for bioinformatics
Introduction to mongodb for bioinformaticsPierre Lindenbaum
 
JakartaData-JCon.pptx
JakartaData-JCon.pptxJakartaData-JCon.pptx
JakartaData-JCon.pptxEmilyJiang23
 
Playing with d3.js
Playing with d3.jsPlaying with d3.js
Playing with d3.jsmangoice
 
Augmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerceAugmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerceSteven Francia
 
From 0 to 60 in SPARQL in 50 Minutes
From 0 to 60 in SPARQL in 50 MinutesFrom 0 to 60 in SPARQL in 50 Minutes
From 0 to 60 in SPARQL in 50 Minutesewg118
 
The Aggregation Framework
The Aggregation FrameworkThe Aggregation Framework
The Aggregation FrameworkMongoDB
 

Semelhante a Better Web Clients with Mantle and AFNetworking (20)

Introduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopIntroduction to MongoDB and Hadoop
Introduction to MongoDB and Hadoop
 
(Big) Data Serialization with Avro and Protobuf
(Big) Data Serialization with Avro and Protobuf(Big) Data Serialization with Avro and Protobuf
(Big) Data Serialization with Avro and Protobuf
 
Modernizes your objective C - Oliviero
Modernizes your objective C - OlivieroModernizes your objective C - Oliviero
Modernizes your objective C - Oliviero
 
Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015
 
Aggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days MunichAggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days Munich
 
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013
 
PostgreSQL 9.3 and JSON - talk at PgOpen 2013
PostgreSQL 9.3 and JSON - talk at PgOpen 2013PostgreSQL 9.3 and JSON - talk at PgOpen 2013
PostgreSQL 9.3 and JSON - talk at PgOpen 2013
 
Building Go Web Apps
Building Go Web AppsBuilding Go Web Apps
Building Go Web Apps
 
Bind me if you can
Bind me if you canBind me if you can
Bind me if you can
 
Expressive objects
Expressive objectsExpressive objects
Expressive objects
 
Modern C++
Modern C++Modern C++
Modern C++
 
IT Days - Parse huge JSON files in a streaming way.pptx
IT Days - Parse huge JSON files in a streaming way.pptxIT Days - Parse huge JSON files in a streaming way.pptx
IT Days - Parse huge JSON files in a streaming way.pptx
 
Webinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev TeamsWebinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev Teams
 
The Ring programming language version 1.6 book - Part 25 of 189
The Ring programming language version 1.6 book - Part 25 of 189The Ring programming language version 1.6 book - Part 25 of 189
The Ring programming language version 1.6 book - Part 25 of 189
 
Introduction to mongodb for bioinformatics
Introduction to mongodb for bioinformaticsIntroduction to mongodb for bioinformatics
Introduction to mongodb for bioinformatics
 
JakartaData-JCon.pptx
JakartaData-JCon.pptxJakartaData-JCon.pptx
JakartaData-JCon.pptx
 
Playing with d3.js
Playing with d3.jsPlaying with d3.js
Playing with d3.js
 
Augmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerceAugmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerce
 
From 0 to 60 in SPARQL in 50 Minutes
From 0 to 60 in SPARQL in 50 MinutesFrom 0 to 60 in SPARQL in 50 Minutes
From 0 to 60 in SPARQL in 50 Minutes
 
The Aggregation Framework
The Aggregation FrameworkThe Aggregation Framework
The Aggregation Framework
 

Último

All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxAna-Maria Mihalceanu
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 

Último (20)

All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance Toolbox
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 

Better Web Clients with Mantle and AFNetworking

  • 1. Better Web Clients with Mantle & AFNetworking
  • 3. Mantle Model framework for Cocoa and Cocoa Touch
  • 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.
  • 14. NSError *error = nil; TGRBook *book = [TGRBook modelWithDictionary:@{ @"title" : @"The Sandman", @"author" : @"Neil Gaiman", @"genres" : @[@"Graphic Novels", @"Fantasy"], ... } error:&error];
  • 15. NSError *error = nil; TGRBook *book = [TGRBook modelWithDictionary:@{ @"title" : @"The Sandman", @"author" : @"Neil Gaiman", @"genres" : @[@"Graphic Novels", @"Fantasy"], ... } error:&error]; TGRBook *anotherBook = [book copy];
  • 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"];
  • 17. 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"];
  • 19. (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)"; }
  • 20. All this just by subclassing MTLModel
  • 21. Our Book Model could have a JSON representation
  • 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/...", ... }
  • 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)
  • 24. 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
  • 25. MTLJSONSerializing protocol @interface TGRBook : MTLModel <MTLJSONSerializing>
  • 26. MTLJSONSerializing protocol @interface TGRBook : MTLModel <MTLJSONSerializing> Specify how to map properties to JSON keypaths
  • 27. 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
  • 28. + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"author" : @"artistName", @"overview" : @"description", @"identifier" : @"trackId", @"title" : @"trackName", @"coverURL" : @"artworkUrl100" }; }
  • 29. + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"author" : @"artistName", @"overview" : @"description", @"identifier" : @"trackId", @"title" : @"trackName", @"coverURL" : @"artworkUrl100" }; } Only properties with a corresponding ivar
  • 30. + (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
  • 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]; }
  • 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 methods
  • 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
  • 34. + (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
  • 36. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end
  • 37. Mapping JSON child objects @interface TGRUser : MTLModel <MTLJSONSerializing> ! @property (copy, nonatomic, readonly) NSArray *purchasedBooks; @property (copy, nonatomic, readonly) TGRBook *nowReading; ! @end + (NSValueTransformer *)purchasedBooksJSONTransformer {
  • 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]; }
  • 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 {
  • 42. 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];
  • 43. MTLJSONAdapter TGRBook *book = [MTLJSONAdapter modelOfClass:TGRBook.class fromJSONDictionary:JSONDictionary error:&error]; ! ! NSDictionary *dictionary = [MTLJSONAdapter JSONDictionaryFromModel:book];
  • 44. Do we still need Core Data?
  • 45. Do we still need Core Data? Of course!
  • 46. Do we still need Core Data? Of course! Memory efficiency with large datasets
  • 47. Do we still need Core Data? Of course! Memory efficiency with large datasets NSFetchRequest is cool!
  • 48. Do we still need Core Data? Of course! Memory efficiency with large datasets NSFetchRequest is cool! Mantle and Core Data can work together
  • 49. An entity for our Book Model
  • 50. MTLManagedObjectSerializing protocol @interface TGRBook : MTLModel <MTLManagedObjectSerializing>
  • 51. MTLManagedObjectSerializing protocol @interface TGRBook : MTLModel <MTLManagedObjectSerializing> Specify the entity name
  • 52. MTLManagedObjectSerializing protocol @interface TGRBook : MTLModel <MTLManagedObjectSerializing> Specify the entity name Specify how to map properties to managed object attributes
  • 53. 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
  • 54. + (NSString *)managedObjectEntityName { return @"Book"; } ! + (NSDictionary *)managedObjectKeysByPropertyKey { return @{ @"coverURL" : @"coverLink" }; } ! + (NSValueTransformer *)coverURLEntityAttributeTransformer { return [[NSValueTransformer valueTransformerForName:MTLURLValueTransformerName] mtl_invertedTransformer]; }
  • 55. MTLManagedObjectAdapter NSManagedObject *managedBook = [MTLManagedObjectAdapter managedObjectFromModel:book insertingIntoContext:moc error:&error]; ! ! ! TGRBook *book = [MTLManagedObjectAdapter modelOfClass:TGRBook.class fromManagedObject:object error:&error];
  • 56. 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
  • 57. 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) { ... }];
  • 58. 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", ...
  • 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. 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) { ... }];
  • 61. NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results];
  • 62. NSArray *results = JSONResponse[@"results"]; NSValueTransformer *transformer; transformer = [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:TGRBook.class]; NSArray *books = [transformer transformedValue:results]; Mapping can potentially take time
  • 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
  • 64. 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!
  • 65. 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
  • 67. 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); }];
  • 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); }];
  • 70. 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...
  • 71. 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