iOS Api Client: soluzioni a confronto

207
iOS Api Client Soluzioni a confronto Massimo Oliviero - Cappery S.r.l. Francesco Sinopoli - Tiltap S.r.l. Monday, May 28, 12

description

Slides della sessione su iOS Api Client: soluzioni a confronto, tenuta da Massimo Oliviero e Francesco Sinopoli alla WhyMCA 2012. http://www.whymca.org/intervento/ios-api-client-soluzioni-confronto ----- Abbiamo sognato un giorno in cui REST diventerà lo standard per tutti i servizi web, le API saranno progettate e documentate come quelle di Twitter, tutti capiranno il significato di concetti come Risorsa, URI e HATEOAS e il mondo sarà per sempre riconoscente a Roy Fielding. Abbiamo sognato … Poi ci siamo svegliati e siamo andati al lavoro. Puntualmente abbiamo trovato il seguente scenario: applicazione critica, progetto in scadenza, API server inviolabili. Vi ricordate quella battuta in Apollo 13: come incastrare un tubo tondo in un boccaporto quadrato? In questa sessione mostreremo alcune pratiche, prodotte dalle nostre Lesson Learned, per realizzare un client iOS chiamato ad interagire con API remote ponendo l'accento sull'architettura software.

Transcript of iOS Api Client: soluzioni a confronto

Page 1: iOS Api Client: soluzioni a confronto

iOS Api ClientSoluzioni a confronto

Massimo Oliviero - Cappery S.r.l.Francesco Sinopoli - Tiltap S.r.l.

Monday, May 28, 12

Page 2: iOS Api Client: soluzioni a confronto

Chi siamo

Massimo Olivierohttp://www.massimooliviero.net - @maxoly

Co-founder & CEO di Cappery www.cappery.com

Co-founder di # pragma mark www.pragmamark.org

Monday, May 28, 12

Page 4: iOS Api Client: soluzioni a confronto

Disclaimer

• Non è una sessione su REST

• Non è una sessione su sulle API Server

• Non vuole essere una sessione esauriente

Monday, May 28, 12

Page 5: iOS Api Client: soluzioni a confronto

Agenda

• Architettura

• Framework custom

• Framework terze parti: REST Kit

Monday, May 28, 12

Page 6: iOS Api Client: soluzioni a confronto

Scenari

Monday, May 28, 12

Page 7: iOS Api Client: soluzioni a confronto

Scenari

• Scenario AServer Api non REST(ful)

Monday, May 28, 12

Page 8: iOS Api Client: soluzioni a confronto

Scenari

• Scenario AServer Api non REST(ful)

• Scenario BServer API REST(ful)

Monday, May 28, 12

Page 9: iOS Api Client: soluzioni a confronto

Soluzioni

Monday, May 28, 12

Page 10: iOS Api Client: soluzioni a confronto

Soluzioni

A. Easy (w lo spaghetti code!)

Monday, May 28, 12

Page 11: iOS Api Client: soluzioni a confronto

Soluzioni

A. Easy (w lo spaghetti code!)

B. Framework custom

Monday, May 28, 12

Page 12: iOS Api Client: soluzioni a confronto

Soluzioni

A. Easy (w lo spaghetti code!)

B. Framework custom

C. Framework di terze parti

Monday, May 28, 12

Page 13: iOS Api Client: soluzioni a confronto

Un nuovo progetto

Monday, May 28, 12

Page 14: iOS Api Client: soluzioni a confronto

Un nuovo progetto

Monday, May 28, 12

Page 15: iOS Api Client: soluzioni a confronto

Un nuovo progetto• App per la N.A.S.A.

Monday, May 28, 12

Page 16: iOS Api Client: soluzioni a confronto

Un nuovo progetto• App per la N.A.S.A.

• Con tre view (Lista pianeti + Lista rover sul pianeta + dettaglio rover)

Monday, May 28, 12

Page 17: iOS Api Client: soluzioni a confronto

Un nuovo progetto• App per la N.A.S.A.

• Con tre view (Lista pianeti + Lista rover sul pianeta + dettaglio rover)

• Il dettaglio deve mostrare alcuni parametri del rover (es. Opportunity su Marte)

Monday, May 28, 12

Page 18: iOS Api Client: soluzioni a confronto

Un nuovo progetto• App per la N.A.S.A.

• Con tre view (Lista pianeti + Lista rover sul pianeta + dettaglio rover)

• Il dettaglio deve mostrare alcuni parametri del rover (es. Opportunity su Marte)

• Lettura dei dati tramite server API della NASA

Monday, May 28, 12

Page 19: iOS Api Client: soluzioni a confronto

Un nuovo progetto• App per la N.A.S.A.

• Con tre view (Lista pianeti + Lista rover sul pianeta + dettaglio rover)

• Il dettaglio deve mostrare alcuni parametri del rover (es. Opportunity su Marte)

• Lettura dei dati tramite server API della NASA

• 10 gg/u

Monday, May 28, 12

Page 20: iOS Api Client: soluzioni a confronto

Dominio

Planet Rover Cam1 n 1 n

Geo

1

1

Monday, May 28, 12

Page 21: iOS Api Client: soluzioni a confronto

Server

• REQUESTGET /opportuniy_get_info.aspx?id=11A1&planet=mars

• RESPONSEcontent-type: text/html

Monday, May 28, 12

Page 22: iOS Api Client: soluzioni a confronto

Server

• REQUESTGET /opportuniy_get_info.aspx?id=11A1&planet=mars

• RESPONSEcontent-type: text/html

Monday, May 28, 12

Page 23: iOS Api Client: soluzioni a confronto

Non ci REST che piang!

Monday, May 28, 12

Page 24: iOS Api Client: soluzioni a confronto

Non ci REST che piang!

Monday, May 28, 12

Page 25: iOS Api Client: soluzioni a confronto

Non ci REST che piang!

Accettiamo la sfida!

Monday, May 28, 12

Page 26: iOS Api Client: soluzioni a confronto

Soluzione Bsviluppiamo un framework custom

Monday, May 28, 12

Page 27: iOS Api Client: soluzioni a confronto

Framework custom

Domande

• Cosa vuol dire sviluppare un framework custom?

• Quando sviluppare un framework custom?

• Quali sono i vantaggi?

• Quali sono gli svantaggi?

Monday, May 28, 12

Page 28: iOS Api Client: soluzioni a confronto

Architetturaun approccio graduale

Monday, May 28, 12

Page 29: iOS Api Client: soluzioni a confronto

Layers

Monday, May 28, 12

Page 30: iOS Api Client: soluzioni a confronto

LayersView

Monday, May 28, 12

Page 31: iOS Api Client: soluzioni a confronto

LayersView

Controller

Monday, May 28, 12

Page 32: iOS Api Client: soluzioni a confronto

Layers

Network Layer

View

Controller

Monday, May 28, 12

Page 33: iOS Api Client: soluzioni a confronto

Layers

Network Layer

View

Controller

Domain Model Layer

Monday, May 28, 12

Page 34: iOS Api Client: soluzioni a confronto

Layers

Network Layer

View

Controller

Domain Model Layer

Data Layer

Monday, May 28, 12

Page 35: iOS Api Client: soluzioni a confronto

Layers

Network Layer

View

Controller

Domain Model Layer

Data Layer

Business Layer

Monday, May 28, 12

Page 36: iOS Api Client: soluzioni a confronto

Layers

Network Layer

View

Controller

Domain Model Layer

Data Layer

Business Layer

Monday, May 28, 12

Page 37: iOS Api Client: soluzioni a confronto

Example Code

PMStarterKitPragma Mark Starter Kithttps://github.com/pragmamark/PMStarterKit

PMTouchPragma Mark iOS General Purpose Libraryhttps://github.com/pragmamark/PMTouch

Monday, May 28, 12

Page 38: iOS Api Client: soluzioni a confronto

Network Layeril primo mattoncino della nostra architettura

Monday, May 28, 12

Page 39: iOS Api Client: soluzioni a confronto

Network Layer

Cosa deve fare

• Gestire URL e risorse

• Gestire request e response

• Gestire proxy & authentication

• Gestire la cache (Cache-Control & ETag)

Monday, May 28, 12

Page 40: iOS Api Client: soluzioni a confronto

Request

Monday, May 28, 12

Page 41: iOS Api Client: soluzioni a confronto

Request

Request

Network Layer

Monday, May 28, 12

Page 42: iOS Api Client: soluzioni a confronto

Request

Cosa deve fare

• Incapsulare una singola chiamata di rete ad una risorsa (URL) specifica

• Gestire i verbi HTTP (GET, POST, PUT, DELETE..)

• Gestire i parametri

Monday, May 28, 12

Page 43: iOS Api Client: soluzioni a confronto

NSURLConnection- (void)viewDidLoad{ [super viewDidLoad]; static NSString *url = @"http://..../?p1=v1&p2=v2"; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]]; self.connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];}

.....

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection- (void)connection:(NSURLConnection *)theConnection didReceiveResponse:(NSURLResponse *)response

Monday, May 28, 12

Page 44: iOS Api Client: soluzioni a confronto

Monday, May 28, 12

Page 45: iOS Api Client: soluzioni a confronto

NSURLConnection

Monday, May 28, 12

Page 46: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

Monday, May 28, 12

Page 47: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

Monday, May 28, 12

Page 48: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

• Documentato

Monday, May 28, 12

Page 49: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

• Documentato

• Flessibile

Monday, May 28, 12

Page 50: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

• Documentato

• Flessibile

Monday, May 28, 12

Page 51: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

• Documentato

• Flessibile

Monday, May 28, 12

Page 52: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

• Documentato

• Flessibile

Contro

Monday, May 28, 12

Page 53: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

• Documentato

• Flessibile

Contro

• Povero

Monday, May 28, 12

Page 54: iOS Api Client: soluzioni a confronto

NSURLConnectionPro

• Nativo

• Documentato

• Flessibile

Contro

• Povero

• Verboso

Monday, May 28, 12

Page 55: iOS Api Client: soluzioni a confronto

Alternative

• ASIHTTPRequesthttps://github.com/pokeb/asi-http-request/tree

• AFNetwork (by Gowalla)https://github.com/AFNetworking/AFNetworking

• MKNetworkKithttps://github.com/MugunthKumar/MKNetworkKit

Monday, May 28, 12

Page 57: iOS Api Client: soluzioni a confronto

ASIHTTPRequest- (void)viewDidLoad{ [super viewDidLoad]; NSURL *url = [NSURL URLWithString:@"http://www.apple.com"]; ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:url]; self.request = request; [request release]; [self.request setDelegate:self]; [self.request startAsynchronous];}

- (void)requestStarted:(ASIHTTPRequest *)request{}

- (void)requestFinished:(ASIHTTPRequest *)request{}

- (void)requestFailed:(ASIHTTPRequest *)request{}

Monday, May 28, 12

Page 58: iOS Api Client: soluzioni a confronto

AFNetworking

• HTTP Requests (cancelled, suspended / resumed)

• Authenticating requests with HTTP Basic credentials or an OAuth token

• Blocks

• feature-rich APIs

Monday, May 28, 12

Page 59: iOS Api Client: soluzioni a confronto

AFNetworkigNSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];

NSURLRequest *request = [NSURLRequest requestWithURL:url];

AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"Public Timeline: %@", JSON);} failure:nil];[operation start];

Monday, May 28, 12

Page 60: iOS Api Client: soluzioni a confronto

Response

Network Layer

Monday, May 28, 12

Page 61: iOS Api Client: soluzioni a confronto

Response

Network Layer

Monday, May 28, 12

Page 62: iOS Api Client: soluzioni a confronto

Response

Request

Network Layer

Monday, May 28, 12

Page 63: iOS Api Client: soluzioni a confronto

Response

Request Response

Network Layer

Monday, May 28, 12

Page 64: iOS Api Client: soluzioni a confronto

Response

Request Response

Network Layer

Monday, May 28, 12

Page 65: iOS Api Client: soluzioni a confronto

Response

Request Response

Network Layer

Monday, May 28, 12

Page 66: iOS Api Client: soluzioni a confronto

Response

Request Response

Network Layer

Monday, May 28, 12

Page 67: iOS Api Client: soluzioni a confronto

Response

Cosa deve fare

• Incapsulare l’HTTP Response (Header, Status code etc.)

• Payload (HTTP Content body)

• Result (JSON > NSArray/NSDictionary etc.)

• Error

Monday, May 28, 12

Page 68: iOS Api Client: soluzioni a confronto

Response@interface PMTResponse : NSObject{ PMTRequest *_request; NSString *_contentBody; NSError *_error; NSObject *_result;}

@property (nonatomic, retain, readonly) PMTRequest *request;@property (nonatomic, retain, readonly) NSString *contentBody;@property (nonatomic, retain, readonly) NSError *error;@property (nonatomic, retain, readonly) NSObject *result;

- (id)initWithRequest:(PMTRequest *)request;- (id)initWithRequest:(PMTRequest *)request result:(NSObject *)result;- (id)initWithRequest:(PMTRequest *)request result:(NSObject *)result error:(NSError *)error;

@end

Monday, May 28, 12

Page 69: iOS Api Client: soluzioni a confronto

Parser

Cosa deve fare

• Trasformare stringhe o dati binari in strutture dati native (es. da JSon a NSArray).

Monday, May 28, 12

Page 70: iOS Api Client: soluzioni a confronto

JSON Parser

Alcune librerie

• NSJSONSerialization

• JSONKit

• SBJson

Benckmarkshttps://github.com/samsoffes/json-benchmarks

Monday, May 28, 12

Page 71: iOS Api Client: soluzioni a confronto

XML ParserAlcune librerie

• NSXMLParser (modalità SAX)

• libxml2 (C Library SAX e DOM)

• TBXML (DOM)

• TouchXML (NSXML DOM)

• KissXML (NSXML DOM)

• TinyXML (C Library DOM)

Monday, May 28, 12

Page 72: iOS Api Client: soluzioni a confronto

Cache

Network Layer

Monday, May 28, 12

Page 73: iOS Api Client: soluzioni a confronto

Cache

Network Layer

Monday, May 28, 12

Page 74: iOS Api Client: soluzioni a confronto

Cache

Request

Network Layer

Monday, May 28, 12

Page 75: iOS Api Client: soluzioni a confronto

Cache

Request Response

Network Layer

Monday, May 28, 12

Page 76: iOS Api Client: soluzioni a confronto

Cache

Request Response Cache

Network Layer

Monday, May 28, 12

Page 77: iOS Api Client: soluzioni a confronto

Cache

Request Response Cache

Network Layer

Monday, May 28, 12

Page 78: iOS Api Client: soluzioni a confronto

Cache

Request Response Cache

Network Layer

Monday, May 28, 12

Page 79: iOS Api Client: soluzioni a confronto

Cache

Cosa deve fare

• Gestire la direttiva cache-control

• Gestire la direttiva ETag

• Storage policy: per session o permanent

Monday, May 28, 12

Page 80: iOS Api Client: soluzioni a confronto

Cache

• A cosa serveA gestire la cache

• Quando utilizzarlaQuando il server lo prevede e lo gestisce in modo efficente ed efficace con le direttive HTTP.

• Perché utilizzarlaPerché diminuisce il traffico di rete e di conseguenza aumenta la responsività dell’app.

Monday, May 28, 12

Page 81: iOS Api Client: soluzioni a confronto

Client

Network Layer

Monday, May 28, 12

Page 82: iOS Api Client: soluzioni a confronto

Client

Network Layer

Monday, May 28, 12

Page 83: iOS Api Client: soluzioni a confronto

Client

Request

Network Layer

Monday, May 28, 12

Page 84: iOS Api Client: soluzioni a confronto

Client

Request Response

Network Layer

Monday, May 28, 12

Page 85: iOS Api Client: soluzioni a confronto

Client

Request Response Cache

Network Layer

Monday, May 28, 12

Page 86: iOS Api Client: soluzioni a confronto

Client

Request Response Cache Client

Network Layer

Monday, May 28, 12

Page 87: iOS Api Client: soluzioni a confronto

Client

Request Response Cache Client

Network Layer

Monday, May 28, 12

Page 88: iOS Api Client: soluzioni a confronto

Client

Cosa deve fare

• Gestire ambienti diversi (produzione, sviluppo, stage, etc.)

• Aprire e chiudere tunnel ssh o vpn

• Gestire l’autenticazione

Monday, May 28, 12

Page 89: iOS Api Client: soluzioni a confronto

Client

• A cosa serveAd incapsulare le request in ambienti specifici.

• Quando utilizzarloQuando si gestiscono ambienti diversi (stage, prod. etc.) o quando si utilizzano tunnel SSH o VPN.

• Perché utilizzarloPer isolare la gestione di queste specifiche funzionalità.

Monday, May 28, 12

Page 90: iOS Api Client: soluzioni a confronto

Client@interface PMTClient : NSObject{ NSURL *_baseUrl; NSString *_username; NSString *_password;}

@property (nonatomic, retain, readonly) NSURL *baseUrl;@property (nonatomic, copy) NSString *username;@property (nonatomic, copy) NSString *password;

- (id)initWithBaseURL:(NSURL *)baseUrl;- (id)initWithBaseURL:(NSURL *)baseUrl username:(NSString *)username password:(NSString *)password;

- (PMTRequest *)createRequest:(NSString *)stringUrl delegate:(id<PMTRequestDelegate>)delegate;

Monday, May 28, 12

Page 91: iOS Api Client: soluzioni a confronto

Network Manager

Network Layer

Monday, May 28, 12

Page 92: iOS Api Client: soluzioni a confronto

Network Manager

Request

Network Layer

Monday, May 28, 12

Page 93: iOS Api Client: soluzioni a confronto

Network Manager

Request Response

Network Layer

Monday, May 28, 12

Page 94: iOS Api Client: soluzioni a confronto

Network Manager

Request Response Cache

Network Layer

Monday, May 28, 12

Page 95: iOS Api Client: soluzioni a confronto

Network Manager

Request Response Cache Client

Network Layer

Monday, May 28, 12

Page 96: iOS Api Client: soluzioni a confronto

Network Manager

Request Response Cache Client

Network Manager

Network Layer

Monday, May 28, 12

Page 97: iOS Api Client: soluzioni a confronto

Network Manager

Cosa deve fare

• Creare ed eseguire le request tramite il client

• Gestire le code di request

• Gestire il suspend e il resume

Monday, May 28, 12

Page 98: iOS Api Client: soluzioni a confronto

Network Manager• A cosa serve

A governare il network layer.

• Quando utilizzarloQuando si vuole disaccopiare e gestire attività complesse come le code, etc.

• Perché utilizzarloDisaccoppia il view controller dall’implementazione di rete e di conseguenza aumenta la manutenibilità del codice.

Monday, May 28, 12

Page 99: iOS Api Client: soluzioni a confronto

Network Manager@interface PMTNetworkManager : NSObject{ SPKRequestQueue *_requestQueue;}

@property (nonatomic, retain, readonly) PMTRequestQueue *requestQueue;@property (nonatomic, assing) BOOL enableSuspendResume;

- (PMTRequest *)requestAdd:(NSString *)request params:(NSDictionary *)params- (PMTRequest *)requestAdd:(NSString *)request params:(NSDictionary *)params queue:(NSString *)queueName;

- (void)addQueue:(NSString *)queueName;

- (void)requestsStart;- (void)requestsStop;

@end

Monday, May 28, 12

Page 100: iOS Api Client: soluzioni a confronto

Network Layer

Quando utilizzare un networking framework?

• SEMPRE, quando possibile evitare di utilizzare direttamente NSURLConnection. Non ha senso.

• Framework come ASIHTTPRequest o AFNetworking semplicano troppo la vita per non essere utilizzati. (Twitter e Facebook docet)

Monday, May 28, 12

Page 101: iOS Api Client: soluzioni a confronto

Network Layer

Monday, May 28, 12

Page 102: iOS Api Client: soluzioni a confronto

Network LayerIn conclusione

• HTTP Request & Response

• Tunneling SSH/VPN

• Ambienti (stage, produzione etc.)

• Cache (HTTP)

• Network Manager

Monday, May 28, 12

Page 103: iOS Api Client: soluzioni a confronto

Network LayerIn conclusione

• HTTP Request & Response

• Tunneling SSH/VPN

• Ambienti (stage, produzione etc.)

• Cache (HTTP)

• Network Manager

Monday, May 28, 12

Page 104: iOS Api Client: soluzioni a confronto

One more thing...

Monday, May 28, 12

Page 105: iOS Api Client: soluzioni a confronto

One more thing...

Monday, May 28, 12

Page 106: iOS Api Client: soluzioni a confronto

One more thing...

“Oltre che leggere l’app deve poter anche inviare dei comandi al rover!”

Monday, May 28, 12

Page 107: iOS Api Client: soluzioni a confronto

Domain Model Layermodelliamo il nostro business

Monday, May 28, 12

Page 108: iOS Api Client: soluzioni a confronto

Domain Model Layer

Cosa deve fare

• Gestire il dato (entità e relazioni)

• Gestire il comportamento

• Convertire il dato da una forma ad un’altra

Monday, May 28, 12

Page 109: iOS Api Client: soluzioni a confronto

Model

Domain Model Layer

Monday, May 28, 12

Page 110: iOS Api Client: soluzioni a confronto

Model

Domain Model Layer

Monday, May 28, 12

Page 111: iOS Api Client: soluzioni a confronto

Model

Model

Domain Model Layer

Monday, May 28, 12

Page 112: iOS Api Client: soluzioni a confronto

Model

Model

Domain Model Layer

Monday, May 28, 12

Page 113: iOS Api Client: soluzioni a confronto

Model

Cosa deve fare

• Rappresentare l’informazione attraverso l’ausilio di una struttura dati nativa o custom

• Possibilmente oltre al dato dovrebbe incorporare anche il comportamento

Monday, May 28, 12

Page 114: iOS Api Client: soluzioni a confronto

NSDictionary & NSArray

NSDictionary *element = [self.elements objectAtIndex:indexPath.row]; cell.textLabel.text = [element objectForKey:@"name"]; cell.detailTextLabel.text = [element objectForKey:@"description"];

Monday, May 28, 12

Page 115: iOS Api Client: soluzioni a confronto

NSObject@interface PMSKPlanet : NSObject

@property (nonatomic, copy, readonly) NSString *name;@property (nonatomic, retain, readonly) PMSKGalaxy *galaxy;

- (id)initWithName:(NSString *)name galaxy:(PMSKGalaxy *)galaxy;

@end

@interface PMSKGalaxy : NSObject

@property (nonatomic, copy, readonly) NSString *name;@property (nonatomic, retain, readonly) NSArray *planets;

- (id)initWithName:(NSString *)name;

@end

Monday, May 28, 12

Page 116: iOS Api Client: soluzioni a confronto

Mapper

Domain Model Layer

Monday, May 28, 12

Page 117: iOS Api Client: soluzioni a confronto

Mapper

Domain Model Layer

Monday, May 28, 12

Page 118: iOS Api Client: soluzioni a confronto

Mapper

Domain Model Layer

Model

Monday, May 28, 12

Page 119: iOS Api Client: soluzioni a confronto

Mapper

Domain Model Layer

Model Mapper

Monday, May 28, 12

Page 120: iOS Api Client: soluzioni a confronto

Mapper

Cosa deve fare

• Definire le regole di traformazione da una struttura dati ad un’altra (es. NSArray to NSObject)

• Gestire le regole e fornirle su richiesta attraverso un sistema centralizzato

Monday, May 28, 12

Page 121: iOS Api Client: soluzioni a confronto

Object Mapper@interface PMTObjectMapper : NSObject

- (void)mapKey:(NSString *)mapKey toProperty:(NSString *)property;

+ (PMTObjectMapper *)mapperForClass:(Class)class;

@end

PMTObjectMapper *mapper = [PMTObjectMapper mapperForClass:[PMSKGalaxy class]];[mapper mapKey:@"planet_name" toProperty:@"name"];[mapper mapKey:@"solar_distance" toProperty:@"solarDistance"];

Monday, May 28, 12

Page 122: iOS Api Client: soluzioni a confronto

Domain Model

Monday, May 28, 12

Page 123: iOS Api Client: soluzioni a confronto

Domain Model

In conclusione

• Entità e relazioni

• Mappatura

Monday, May 28, 12

Page 124: iOS Api Client: soluzioni a confronto

Domain Model

In conclusione

• Entità e relazioni

• Mappatura

Monday, May 28, 12

Page 125: iOS Api Client: soluzioni a confronto

One more “little” thing

Monday, May 28, 12

Page 126: iOS Api Client: soluzioni a confronto

One more “little” thing

Monday, May 28, 12

Page 127: iOS Api Client: soluzioni a confronto

One more “little” thing

“L’applicazione deve funzionare anche OFFLINE”

Monday, May 28, 12

Page 128: iOS Api Client: soluzioni a confronto

Data Layerpersistiamo i nostri dati

Monday, May 28, 12

Page 129: iOS Api Client: soluzioni a confronto

Data Layer

Cosa deve fare

• Persistere le informazioni

• Recuperare le informazioni

Monday, May 28, 12

Page 130: iOS Api Client: soluzioni a confronto

Store

Data Layer

Monday, May 28, 12

Page 131: iOS Api Client: soluzioni a confronto

Store

Data Layer

Monday, May 28, 12

Page 132: iOS Api Client: soluzioni a confronto

Store

Store

Data Layer

Monday, May 28, 12

Page 133: iOS Api Client: soluzioni a confronto

Store

Store

Data Layer

Monday, May 28, 12

Page 134: iOS Api Client: soluzioni a confronto

File system

• File systemNSCoding, NSKeyedArchiver, NSKeyedUnarchiver

• PlistNSDictionary, NSArray, NSFileManager

Monday, May 28, 12

Page 135: iOS Api Client: soluzioni a confronto

Relational

• FMDB (Objective-C wrapper around SQLite)https://github.com/ccgus/fmdb

• CoreData (object graph & persistence framework)http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/coredata/cdprogrammingguide.html

Monday, May 28, 12

Page 136: iOS Api Client: soluzioni a confronto

Manager

Data Layer

Monday, May 28, 12

Page 137: iOS Api Client: soluzioni a confronto

Manager

Data Layer

Monday, May 28, 12

Page 138: iOS Api Client: soluzioni a confronto

Manager

Store

Data Layer

Monday, May 28, 12

Page 139: iOS Api Client: soluzioni a confronto

Manager

Store

Data Layer

Manager

Monday, May 28, 12

Page 140: iOS Api Client: soluzioni a confronto

Manager

Cosa deve fare

• Fornire un’interfaccia di accesso ai dati persistiti

• Fornire strumenti di interrogazione

Monday, May 28, 12

Page 141: iOS Api Client: soluzioni a confronto

Conclusionie quindi?

Monday, May 28, 12

Page 142: iOS Api Client: soluzioni a confronto

Framework custom

Layer Quando

Network Layer SEMPRE

Domain Model Leggere e scrivere

Data Layer Offline

Monday, May 28, 12

Page 143: iOS Api Client: soluzioni a confronto

Framework custom

Monday, May 28, 12

Page 144: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

Monday, May 28, 12

Page 145: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

• Know-how

Monday, May 28, 12

Page 146: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

• Know-how

• Modulare

Monday, May 28, 12

Page 147: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

• Know-how

• Modulare

• Flessibile (Business)

Monday, May 28, 12

Page 148: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

• Know-how

• Modulare

• Flessibile (Business)

Svantaggi

Monday, May 28, 12

Page 149: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

• Know-how

• Modulare

• Flessibile (Business)

Svantaggi

• Tempo (Costi)

Monday, May 28, 12

Page 150: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

• Know-how

• Modulare

• Flessibile (Business)

Svantaggi

• Tempo (Costi)

• Skill

Monday, May 28, 12

Page 151: iOS Api Client: soluzioni a confronto

Framework custom

Vantaggi

• Know-how

• Modulare

• Flessibile (Business)

Svantaggi

• Tempo (Costi)

• Skill

• Declinato

Monday, May 28, 12

Page 152: iOS Api Client: soluzioni a confronto

Soluzione C

API +

Dominio di Business =

Monday, May 28, 12

Page 153: iOS Api Client: soluzioni a confronto

RestKit

Che cosa è ?Restkit è un framework Objective-C per iOS che ha lo scopo di facilitare l'interazione con i web-service.

Monday, May 28, 12

Page 154: iOS Api Client: soluzioni a confronto

Che cosa fa ?

HTTP PROTOCOLREST SOAP XMLENCODE PARSER

CODE ACTIVE RECORDPATTERN MAPPING

CACHE STRATEGY SQL

RestKit

Monday, May 28, 12

Page 155: iOS Api Client: soluzioni a confronto

Network Layer

“Ha la funzione di costruire e consegnare le richieste HTTP e processare le risposte che arrivano dal server remoto”

Obiettivo

Come raggiunge l’obiettivo?

RKClient RKRequest RKResponse

Attraverso tre attori principali

Monday, May 28, 12

Page 156: iOS Api Client: soluzioni a confronto

Network Layer

RKClientHttp headers - Type Authentication

Base URL

RKClient

App

Monday, May 28, 12

Page 157: iOS Api Client: soluzioni a confronto

Network Layer

RKClientHttp headers - Type Authentication

Base URL

RKClient Http headers - Type Authentication

Base URL

RKClient

App

Monday, May 28, 12

Page 158: iOS Api Client: soluzioni a confronto

Network LayerRKClientRKRequestRKResponse

#import "AppDelegate.h"#import <RestKit/RestKit.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ RKClient *client = [RKClient clientWithBaseURL:@"https://api.pragma-mark.org/sampleQuiz"];...

[RKClient sharedClient]

Da qui in poi avremo disponibile

Monday, May 28, 12

Page 159: iOS Api Client: soluzioni a confronto

Network Layer

@implementation MyViewController...

#pragma mark - View lifecycle

- (void)viewDidLoad{ [super viewDidLoad];

[[RKClient sharedClient] get:@"/collections/questions" delegate:self];}

#pragma mark - Restkit delegate

- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response { NSLog(@"Loaded payload: %@ with code %i", [response bodyAsString], [response statusCode]); }

-(void)request:(RKRequest*)request didFailLoadWithError:(NSError*)error{ NSLog(@"Error %@",[error localizedDescription]);}

#import <UIKit/UIKit.h>#import <RestKit/RestKit.h>

@interface MyViewController : UIViewController<RKRequestDelegate>{...

Una volta configurato un client possiamo inviare e processare richieste HTTP attraverso esso.

Esempio: invio richiesta e visualizzazione risposta

resource path

Monday, May 28, 12

Page 160: iOS Api Client: soluzioni a confronto

Network Layer

?payload

Siamo in grado di comunicare con un

web service remoto, inviare

richieste e processare risposte,

Web Service

Monday, May 28, 12

Page 161: iOS Api Client: soluzioni a confronto

Object Mapping

Quando ne abbiamo bisogno e che cosa è?

Punto di forza di RestKit

E’ un sistema che ci permette di trasformare le risposte JSON/XML in oggetti di dominio locali.

Salendo di astrazione: è un sistema che si occupa di trasformare i dati da un formato ad un altro.

Quando si ha necessità, non solo di scambiare dati, ma di rappresentare oggetti.

Monday, May 28, 12

Page 162: iOS Api Client: soluzioni a confronto

Object Mapping

RKObjectManager RKObjectMapping

RKObjectMapper RKObjectMappingProvider

•Quando carichiamo un risorsa remota tramite un’istanza di RKObjectManager•Quando un oggetto locale è inviato al backend per essere processato

Le operazioni di mapping sono eseguite:

Monday, May 28, 12

Page 163: iOS Api Client: soluzioni a confronto

Il protagonista principale di questo layer è RKObjectManager

“RKObjectManager è la classe che si occupa della trasformazione dei dati contenuti nel payload in oggetti”

Object Mapping

RKObjectManager

App RK

Clie

nt

Monday, May 28, 12

Page 164: iOS Api Client: soluzioni a confronto

Object MappingEsempio: caricare oggetti remoti in oggetti locali

Obiettivo: vogliamo recuperare una collection di question dal web service

Monday, May 28, 12

Page 165: iOS Api Client: soluzioni a confronto

Object MappingEsempio: caricare oggetti remoti in oggetti locali

Il web service ritorna qualcosa di simile a...{ “questions”: [{ "body" : "Che cosa si intende per scope creep?", "correctIdAnswer" : 1, "identifier" : 1},{ "body" : "Che differenza c’è tra lead e lag?", "correctIdAnswer" : 2, "identifier" : 2}]}

Monday, May 28, 12

Page 166: iOS Api Client: soluzioni a confronto

Object MappingEsempio: caricare oggetti remoti in oggetti locali

@interface Question : NSObject

@property (nonatomic, copy) NSNumber* identifier;@property (nonatomic, copy) NSString* body;@property (nonatomic, copy) NSNumber* correctIdAnswer;

@end

...lato client, questi dati sono rappresentati da una classe

Monday, May 28, 12

Page 167: iOS Api Client: soluzioni a confronto

Object Mapping

RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:@"https://api.pragmamark.org/quiz"]; RKObjectMapping* questionMapping = [RKObjectMapping mappingForClass:[Question class]];[questionMapping mapKeyPath:@"identifier" toAttribute:@"identifier"];[questionMapping mapKeyPath:@"body" toAttribute:@"body"];[questionMapping mapKeyPath:@"correctIdAnswer" toAttribute:@"correctIdAnswer"]; [objectManager.mappingProvider setMapping:questionMapping forKeyPath:@"questions"];

Configuriamo RestKit Definiamo un mapping per

la classe Question

Istruiamo il mapping provider ad usare questionMapping se incontra un

@”questions” key path

Un esempio: caricare oggetti remoti in oggetti locali

Monday, May 28, 12

Page 168: iOS Api Client: soluzioni a confronto

Object MappingUn esempio: caricare oggetti remoti in oggetti locali

[[RKObjectManager sharedManager] loadObjectsAtResourcePath:@”/questions" delegate:self];

Carichiamo gli oggetti

...i dati vengono recuperati, parserizzati e assegnati agli oggetti locali- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {! NSLog(@"Loaded statuses: %@", objects); }

La classe deve implementare RKObjectLoaderDelegate

Monday, May 28, 12

Page 169: iOS Api Client: soluzioni a confronto

Object Mapping

Siamo in grado di comunicare con un

web service remoto, inviare

richieste e processare risposte

Caricare rappresentazioni di

oggetti remotinella nostra App e mapparli in oggeti

locali

Monday, May 28, 12

Page 170: iOS Api Client: soluzioni a confronto

Object Mapping

JSONXML...

payloadServer

Inviare oggetti al server

(Serialization)

Monday, May 28, 12

Page 171: iOS Api Client: soluzioni a confronto

Object Mapping

RKObjectSerializer

Local Domain Objects

IntermediateDictionary

(NSMutableDictionary)

Mapping Encoder[{ "body" : "Che cosa si intende per scope creep?",

"correctIdAnswer" : 1,

"identifier" : 1

},

{ "body" : "Che differenza c’è tra lead e lag?",

"correctIdAnswer" : 2,

"identifier" : 2

JSON(XML, URL Form Encode...)

BackendSystem

RKParser

attributi e relazioni

Serialization? Un’altra operazione di mapping.

Requ

est

Monday, May 28, 12

Page 172: iOS Api Client: soluzioni a confronto

Object Mapping Un esempio: inviare oggetti locale al server remoto

[[RKObjectManager sharedManager].router routeClass:[Question class] toResourcePath:@"/questions" forMethod:RKRequestMethodPOST];

[[RKObjectManager sharedManager] setSerializationMIMEType:RKMIMETypeJSON];RKObjectMapping* questionSerializationMapping = [questionMapping inverseMapping];[[RKObjectManager sharedManager].mappingProvider setSerializationMapping:questionSerializationMapping forClass:[Question class]];

Configuriamo RestKit

Lo stesso mapping definito prima è

utilizzo per serializzare la classe

Istruiamo il mapping provider ad usare

questionSerializationMapping

Monday, May 28, 12

Page 173: iOS Api Client: soluzioni a confronto

Object Mapping

// Create a new Question and POST it to the serverQuestion* question = [Question new];question.body = @"Cosa si intende per approccio agile ad un progetto?";question.identifier = [NSNumber numberWithInt: 3];

Creiamo l’oggetto

[[RKObjectManager sharedManager] postObject:question delegate:self];Inviamo la richiesta...

...recuperiamo la risposta dal server- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {! NSLog(@"Loaded statuses: %@", objects); }

RestKit sa che deve serializzare quando

esegue un POST o un PUT

Un esempio: inviare oggetti locale al server remoto

Monday, May 28, 12

Page 174: iOS Api Client: soluzioni a confronto

RoutingOvvero, dove vivono gli oggetti?

RKObjectRouter

RestKit offre un sistema di routing capace di generare resource path per un oggetto.

RKObjectRouter registra un mapping tra una classe del dominio e un resource path per uno specifico metodo HTTP.

Per interagire con un web service è necessario sapere dove gli oggetti risiedono.

RoutingSystem

/questions/123

/questions/654/questions/789

Monday, May 28, 12

Page 175: iOS Api Client: soluzioni a confronto

RoutingOvvero, dove vivono gli oggetti?

[[RKObjectManager sharedManager].router routeClass:[Question class] toResourcePath:@"/questions" forMethod:RKRequestMethodPOST];

POST

[[RKObjectManager sharedManager].router routeClass:[Question class] toResourcePath:@"/questions/(idpk)" forMethod:RKRequestMethodPUT];

PUT

[[RKObjectManager sharedManager].router routeClass:[Question class] toResourcePath:@"/questions/(idpk)" forMethod:RKRequestMethodDELETE];

DELETE

GET[[RKObjectManager sharedManager].router routeClass:[Question class] toResourcePath:@"/questions/(idpk)" forMethod:RKRequestMethodGET];

Monday, May 28, 12

Page 176: iOS Api Client: soluzioni a confronto

Routing

[[RKObjectManager sharedManager].router routeClass:[Question class] toResourcePath:@"/questions" forMethod:RKRequestMethodPOST];

[[RKObjectManager sharedManager].router routeClass:[Question class] toResourcePath:@"/questions/(identifier)"];

Inizializziamo il nostro route...

Definiamo default route che

sarà usato per tutti gli HTTP

verbs (GET, POST, PUT e DELETE)

registriamo uno specifico

route per il verbo POST

Un esempio: inviare un oggetto al server

Monday, May 28, 12

Page 177: iOS Api Client: soluzioni a confronto

Routing

// Nel setup dell’App abbiamo già definito i mapping per questa classe Question* question = [Question new]; question.body = @"Cosa si intende per approccio agile ad un progetto?";

[[RKObjectManager sharedManager] postObject:question delegate:self];

POST

Un esempio: inviare oggetti locale al server remoto

RKObjectRouter è quindi utilizzato per generare resource path quando utilizziamo getObject, deleteObject, postObject e putObject.

“/questions”

Monday, May 28, 12

Page 178: iOS Api Client: soluzioni a confronto

Routing

Question *question = [Question new]; question.body = @"Che cosa si intende per scope creep?"; question.identifier = [NSNumber numberWithInt: 3];

[[RKObjectManager sharedManager] putObject:question delegate:self];

PUT

Un esempio: inviare oggetti locale al server remoto

RKObjectRouter è quindi utilizzato per generare resource path quando utilizziamo getObject, deleteObject, postObject e putObject.

“/questions/3”

Monday, May 28, 12

Page 179: iOS Api Client: soluzioni a confronto

Routing

Question *question = [Question new];question.identifier = [NSNumber numberWithInt: 3];

[[RKObjectManager sharedManager] deleteObject:question delegate:self];

DELETE

Un esempio: inviare oggetti locale al server remoto

RKObjectRouter è quindi utilizzato per generare resource path quando utilizziamo getObject, deleteObject, postObject e putObject.

“/questions/3”

Monday, May 28, 12

Page 180: iOS Api Client: soluzioni a confronto

Offline :|Core Data Integration

A questo punto, cosa siamo in grado di fare?

Interagire con il web service remoto

Rappresentare le risorse remote in

locale

Modificare e inviare oggetti

locali al backend

Monday, May 28, 12

Page 181: iOS Api Client: soluzioni a confronto

Offline :|Core Data Integration

Assenza di connettività?

Monday, May 28, 12

Page 182: iOS Api Client: soluzioni a confronto

Offline :)Core Data Integration

Assenza di connettività?Persistiamo i dati in locale con Core Data

Monday, May 28, 12

Page 183: iOS Api Client: soluzioni a confronto

OfflineCore Data Integration

RKManagedObjectStore RKManagedObjectMapping

RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:@”http://pragmamark.org]; objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@”Quiz.sqlite];

Setup RestKit

Vediamo come fare passo dopo passo.

Indicare lo store1

Monday, May 28, 12

Page 184: iOS Api Client: soluzioni a confronto

Mapping

Vediamo come fare passo dopo passo.

Utilizzare RKManagedObjectMapping2

Questo permette al Mapper di discriminare tra oggetti nuovi, aggiornati o

eliminati

3

OfflineCore Data Integration

RKManagedObjectMapping* questionMapping = [RKManagedObjectMapping mappingForClass:[Question class]]; questionMapping.primaryKeyAttribute = @"identifier"; [questionMapping mapKeyPath:@"identifier" toAttribute:@"identifier"];[questionMapping mapKeyPath:@"body" toAttribute:@"body"];[questionMapping mapKeyPath:@"correctIdAnswer" toAttribute:@"correctIdAnswer"]; [objectManager.mappingProvider setMapping:questionMapping forKeyPath:@"questions"];

Monday, May 28, 12

Page 185: iOS Api Client: soluzioni a confronto

OfflineCore Data Integration

Il modello persistente deve

ereditare da NSManagedObject

4

@interface Question : NSManagedObject

@property (nonatomic, copy) NSNumber* identifier;@property (nonatomic, copy) NSString* body;@property (nonatomic, copy) NSNumber* correctIdAnswer;

@end

Monday, May 28, 12

Page 186: iOS Api Client: soluzioni a confronto

@implementation Question

@synthesize identifier;@synthesize body;@synthesize correctIdAnswer;

@end

@implementation Question

@dynamic identifier;@dynamic body;@dynamic correctIdAnswer;

@end @dynamic vs @synthesize

5

OfflineCore Data Integration

Monday, May 28, 12

Page 187: iOS Api Client: soluzioni a confronto

2012-05-20 12:03:20.921 WhyMCA[1060:fb03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot initialize an RKManagedObjectMapping without an entity. Maybe you want RKObjectMapping instead?'

Data Model Data Model resource6

OfflineCore Data Integration

Monday, May 28, 12

Page 188: iOS Api Client: soluzioni a confronto

Ora che succede?

Local Domains Objectsmapping

{questions: [

{ "body" : "Che cosa si intende per scope creep?",

"correctIdAnswer" : 1,

"identifier" : 1

},

{ "body" : "Che differenza c’è tra lead e lag?",

"correctIdAnswer" : 2,

"identifier" : 2

}]

}

JSON(XML, Form URL Encode...)

Transientobjects

Persistentobjects

OfflineCore Data Integration

Monday, May 28, 12

Page 189: iOS Api Client: soluzioni a confronto

[[RKObjectManager sharedManager] loadObjectsAtResourcePath:@”/questions" delegate:self];

Dopo aver fatto richieste al server...

...i dati sono recuperati, parserizzati e assegnati agli oggetti locali- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {! NSLog(@"Loaded questions: %@", objects); }

OfflineCore Data Integration

Un esempio: chiedere i dati al server

Monday, May 28, 12

Page 190: iOS Api Client: soluzioni a confronto

2012-05-20 12:29:00.757 WhyMCA [1499:fb03] Loaded questions: ( "<Question: 0x6b921b0> (entity: Question; id: 0x6e704e0 <x-coredata://62C52FE3-86E9-4FD0-9BA8-FAE16839477E/Question/p1> ; data: <fault>)", "<Question: 0x6b8f090> (entity: Question; id: 0x6e707a0 <x-coredata://62C52FE3-86E9-4FD0-9BA8-FAE16839477E/Question/p5> ; data: <fault>)", }

2012-05-13 16:01:03.478 WhyMCA[9935:fb03] Loaded questions: ( "<Question: 0x83a1bd0>", "<Question: 0x83a57d0>")

OfflineCore Data Integration

Un esempio: chiedere i dati al server

Monday, May 28, 12

Page 191: iOS Api Client: soluzioni a confronto

if ([[RKObjectManager sharedManager] isOnline]) { [[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/questions" delegate:self];}else { NSArray *questions = [Question allObjects];}

Impostiamo la nostra tecnica

Alternative?

•Implementare di RKManagedObjectCache protocol•Utilizzare RKRequestCache •Database seeding

Un esempio: chiedere i dati al server

OfflineCore Data Integration

Monday, May 28, 12

Page 192: iOS Api Client: soluzioni a confronto

In practiceRestKit Mapping & CoreData

“Non sempre le risposte del web service sono come ce le aspettiamo”(Anonimo)

Team Mobile Team Server-side

Monday, May 28, 12

Page 193: iOS Api Client: soluzioni a confronto

•Aggiungiamo l’entità Answer

•Question e Answer sono in relazione molti a molti

•L’identificativo di Question è in un oggetto nidificato

•Nell’elenco delle question manca la key Path @”questions”

Elaboriamo un pò il nostro model

In practiceRestKit Mapping & CoreData

Monday, May 28, 12

Page 194: iOS Api Client: soluzioni a confronto

RestKit Mapping & CoreDataIn practice

{ “questions”: [ { "identifier" : 1 "body" : "Che cosa si intende per scope creep?", "correctIdAnswer" : 1, }, { "identifier" : 2 "body" : "Che differenza c’è tra lead e lag?", "correctIdAnswer" : 2, }]}

{ [ {"_id": {        "$identifier": "4faf69fee4b0895a3ed9b1ff"    },    "correctIdAnswer": 1,    "body": "Quale è il significato del termine lead?",    "answers": [        {            "identifier": "3",            "body": "risposta B"        },        {            "identifier": "1",            "body": "risposta A"        }    ] }, {...

Dove è la key @“questions” ?Come identifichiamo il contenuto?

Monday, May 28, 12

Page 195: iOS Api Client: soluzioni a confronto

@interface Answer : NSManagedObject

@property (nonatomic, copy) NSString* identifier;@property (nonatomic, copy) NSString* body;@property (nonatomic, retain) NSSet* questions;

@end

In practiceRestKit Mapping & CoreData

@interface Question : NSManagedObject

@property (nonatomic, copy) NSString* identifier;@property (nonatomic, copy) NSString* body;@property (nonatomic, copy) NSNumber* correctIdAnswer;@property (nonatomic, retain) NSSet* answers;

@end

Monday, May 28, 12

Page 196: iOS Api Client: soluzioni a confronto

In practiceRestKit Mapping & CoreData

//MappingRKManagedObjectMapping* questionMapping = [RKManagedObjectMapping mappingForClass:[Question class]];questionMapping.primaryKeyAttribute = @"identifier";[questionMapping mapKeyPath:@"_id.$identifier" toAttribute:@"identifier"];[questionMapping mapKeyPath:@"body" toAttribute:@"body"];[questionMapping mapKeyPath:@"correctIdAnswer" toAttribute:@"correctIdAnswer"];

RKManagedObjectMapping* answerMapping = [RKManagedObjectMapping mappingForClass:[Answer class]]; [answerMapping setPrimaryKeyAttribute:@"identifier"];[answerMapping mapKeyPath:@"identifier" toAttribute:@"identifier"];[answerMapping mapKeyPath:@"body" toAttribute:@"body"];

[questionMapping mapKeyPath:@"answers" toRelationship:@"answers" withMapping:answerMapping];[objectManager.mappingProvider addObjectMapping:questionMapping];

Monday, May 28, 12

Page 197: iOS Api Client: soluzioni a confronto

In practiceRestKit Mapping & CoreData

Effettuiamo la richiesta al server...RKObjectMapping *questionMapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[Question class]];

[[RKObjectManager sharedManager] loadObjectsAtResourcePath:@”/questions" objectMapping:questionMapping delegate:self];

Monday, May 28, 12

Page 198: iOS Api Client: soluzioni a confronto

[[RKObjectManager sharedManager] postObject:question delegate:self block:^(RKObjectLoader* loader) { loader.objectMapping = [RKObjectMapping mappingForClass:[Question class] block:^(RKObjectMapping* mapping) { [mapping mapAttributes:@"identifier", @"body", nil]; }]; }];

In practiceRestKit Mapping & CoreData

Possiamo costruire un mapping dinamicamente...

Monday, May 28, 12

Page 199: iOS Api Client: soluzioni a confronto

Le codeInviare richieste e processare risposte: i retroscena.

RKResponse

RKClient

RKRequest

Payload

Monday, May 28, 12

Page 200: iOS Api Client: soluzioni a confronto

Le codeInviare richieste e processare risposte: i retroscena.

RKResponse

RKClient

RKRequest

Payload

RKRequestQueue

Monday, May 28, 12

Page 201: iOS Api Client: soluzioni a confronto

//[[RKClient sharedClient].requestQueue addRequest:loader];

Cosa succede quando inviamo una richiesta con RKRequest?[RKClient sharedClient].requestQueue

[[RKClient sharedClient].requestQueue cancelRequestsWithDelegate:delegate];

•rilevare connettività•limitare le richieste concorrenti•eliminare richieste per un determinato delegato

RKRequestQueue è utilizzato anche per:

Le codeInviare richieste e processare risposte: i retroscena.

Monday, May 28, 12

Page 202: iOS Api Client: soluzioni a confronto

Possiamo usarle per:

•Effettuare il download di un’entità “complessa”. Ad esempio: ipotizziamo una Guida, entità del dominio, rappresentata da un grafo di oggetti contenente le sue proprietà e le sue relazioni ma che fa riferimento a diversi asset (audio, fotografie, tiles per le mappa offline) attraverso percorsi esterni.

•Raggruppare le chiamate per la paginazione, per la ricerca, per il workflow di acquisto, etc.. e utilizzare la sharedQueue per soddisfare la user action.

Le codeInviare richieste e processare risposte: i retroscena.

Monday, May 28, 12

Page 203: iOS Api Client: soluzioni a confronto

Le codeInviare richieste e processare risposte: i retroscena.

RKRequestQueue *queue = [RKRequestQueue requestQueueWithName:nameQueue];

queue.concurrentRequestsLimit = 5;

Creare una coda...

Monday, May 28, 12

Page 204: iOS Api Client: soluzioni a confronto

Le codeInviare richieste e processare risposte: i retroscena.

NSString *resourcePath = [NSString stringWithFormat:@"%@%@/%i",kAPIAddress,kAPI_AUDIO_GET,[identifier intValue]]; RKRequest *request = [RKRequest requestWithURL:[NSURL URLWithString:resourcePath] delegate:self];request.authenticationType = RKRequestAuthenticationTypeHTTPBasic;request.username = [RKClient sharedClient].username;request.password = [RKClient sharedClient].password; [queue addRequest:request][queue start];

Aggiungere richieste...

Monday, May 28, 12

Page 205: iOS Api Client: soluzioni a confronto

Le codeInviare richieste e processare risposte: i retroscena.

//verifica prima se esiste la queueBOOL existsQueue = [RKRequestQueue requestQueueExistsWithName:nameQueue]; if (existsQueue) { RKRequestQueue *queue = [RKRequestQueue requestQueueWithName:nameQueue]; NSLog(@"Elimino richieste in coda %i",[queue count]); [queue cancelAllRequests]; NSLog(@"Richieste in coda %i",[queue count]);}

Svuotare la coda...

Monday, May 28, 12

Page 206: iOS Api Client: soluzioni a confronto

Conclusionie quindi?

Monday, May 28, 12

Page 207: iOS Api Client: soluzioni a confronto

“Buon senso”

Monday, May 28, 12