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. 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.
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
iOS Api Client: soluzioni a confronto
1. iOS Api Client
Soluzioni a confronto
Massimo Oliviero - Cappery S.r.l.
Francesco Sinopoli - Tiltap S.r.l.
Monday, May 28, 12
2. Chi siamo
Massimo Oliviero
http://www.massimooliviero.net - @maxoly
Co-founder & CEO di Cappery
www.cappery.com
Co-founder di # pragma mark
www.pragmamark.org
Monday, May 28, 12
3. Francesco Sinopoli
TILTAP
Superpartes Innovation Campus | H-FARM
@ondadurto
francescosinopoli@hotmail.com
http://it.linkedin.com/in/francescosinopoli
co-founder di # pragma mark
www.pragmamark.org
Monday, May 28, 12
4. Disclaimer
• Non è una sessione su REST
• Non è una sessione su sulle API Server
• Non vuole essere una sessione esauriente
Monday, May 28, 12
16. 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
17. 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
18. 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
19. 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
20. Dominio
1 n 1 n
Planet Rover Cam
1
1
Geo
Monday, May 28, 12
21. Server
• REQUEST
GET /opportuniy_get_info.aspx?
id=11A1&planet=mars
• RESPONSE
content-type: text/html
Monday, May 28, 12
22. Server
• REQUEST
GET /opportuniy_get_info.aspx?
id=11A1&planet=mars
• RESPONSE
content-type: text/html
Monday, May 28, 12
25. Non ci REST che piang!
Accettiamo la sfida!
Monday, May 28, 12
26. Soluzione B
sviluppiamo un framework custom
Monday, May 28, 12
27. 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
28. Architettura
un approccio graduale
Monday, May 28, 12
32. Layers
View
Controller
Network Layer
Monday, May 28, 12
33. Layers
View
Controller
Domain
Model
Layer
Network Layer
Monday, May 28, 12
34. Layers
View
Controller
Domain
Data
Model
Layer
Layer
Network Layer
Monday, May 28, 12
35. Layers
View
Controller
Domain
Business Data
Model
Layer Layer
Layer
Network Layer
Monday, May 28, 12
36. Layers
View
Controller
Domain
Business Data
Model
Layer Layer
Layer
Network Layer
Monday, May 28, 12
37. Example Code
PMStarterKit
Pragma Mark Starter Kit
https://github.com/pragmamark/PMStarterKit
PMTouch
Pragma Mark iOS General Purpose Library
https://github.com/pragmamark/PMTouch
Monday, May 28, 12
38. Network Layer
il primo mattoncino della nostra architettura
Monday, May 28, 12
39. 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
41. Request
Network Layer
Request
Monday, May 28, 12
42. 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
48. NSURLConnection
Pro
• Nativo
• Documentato
Monday, May 28, 12
49. NSURLConnection
Pro
• Nativo
• Documentato
• Flessibile
Monday, May 28, 12
50. NSURLConnection
Pro
• Nativo
• Documentato
• Flessibile
Monday, May 28, 12
51. NSURLConnection
Pro
• Nativo
• Documentato
• Flessibile
Monday, May 28, 12
52. NSURLConnection
Pro Contro
• Nativo
• Documentato
• Flessibile
Monday, May 28, 12
53. NSURLConnection
Pro Contro
• Nativo • Povero
• Documentato
• Flessibile
Monday, May 28, 12
54. NSURLConnection
Pro Contro
• Nativo • Povero
• Documentato • Verboso
• Flessibile
Monday, May 28, 12
55. Alternative
• ASIHTTPRequest
https://github.com/pokeb/asi-http-request/tree
• AFNetwork (by Gowalla)
https://github.com/AFNetworking/AFNetworking
• MKNetworkKit
https://github.com/MugunthKumar/MKNetworkKit
Monday, May 28, 12
56. ASIHTTPRequest
• Mac OS X & iPhone
• Synchronous & asynchronous requests
• Basic, Digest e NTLM authentication
• Cache control and ETag support
• Throttling bandwidth
Monday, May 28, 12
62. Response
Network Layer
Request
Monday, May 28, 12
63. Response
Network Layer
Request Response
Monday, May 28, 12
64. Response
Network Layer
Request Response
Monday, May 28, 12
65. Response
Network Layer
Request Response
Monday, May 28, 12
66. Response
Network Layer
Request Response
Monday, May 28, 12
67. 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
79. Cache
Cosa deve fare
• Gestire la direttiva cache-control
• Gestire la direttiva ETag
• Storage policy: per session o permanent
Monday, May 28, 12
80. Cache
• A cosa serve
A gestire la cache
• Quando utilizzarla
Quando il server lo prevede e lo gestisce in modo
efficente ed efficace con le direttive HTTP.
• Perché utilizzarla
Perché diminuisce il traffico di rete e di
conseguenza aumenta la responsività dell’app.
Monday, May 28, 12
88. 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
89. Client
• A cosa serve
Ad incapsulare le request in ambienti specifici.
• Quando utilizzarlo
Quando si gestiscono ambienti diversi (stage, prod.
etc.) o quando si utilizzano tunnel SSH o VPN.
• Perché utilizzarlo
Per isolare la gestione di queste specifiche
funzionalità.
Monday, May 28, 12
97. 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
98. Network Manager
• A cosa serve
A governare il network layer.
• Quando utilizzarlo
Quando si vuole disaccopiare e gestire attività
complesse come le code, etc.
• Perché utilizzarlo
Disaccoppia il view controller dall’implementazione
di rete e di conseguenza aumenta la manutenibilità
del codice.
Monday, May 28, 12
100. 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
108. 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
111. Model
Domain Model Layer
Model
Monday, May 28, 12
112. Model
Domain Model Layer
Model
Monday, May 28, 12
113. 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
118. Mapper
Domain Model Layer
Model
Monday, May 28, 12
119. Mapper
Domain Model Layer
Model Mapper
Monday, May 28, 12
120. 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
152. Soluzione C
API +
Dominio di Business =
Monday, May 28, 12
153. 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
154. RestKit
Che cosa fa ?
HTTP PROTOCOL
REST SOAP XML
ENCODE PARSER
CODE ACTIVE RECORD
PATTERN MAPPING
CACHE STRATEGY SQL
Monday, May 28, 12
155. Network Layer
Obiettivo
“Ha la funzione di costruire e consegnare le richieste
HTTP e processare le risposte che arrivano dal server
remoto”
Come raggiunge l’obiettivo?
Attraverso tre attori principali
RKClient RKRequest RKResponse
Monday, May 28, 12
156. Network Layer
Base URL
RKClient
Http headers - Type Authentication
RKClient
App
Monday, May 28, 12
157. Network Layer
Base URL
RKClient
Http headers - Type Authentication
Base URL
RKClient
Http headers - Type Authentication
RKClient
App
Monday, May 28, 12
158. Network Layer
RKClient
RKRequest
RKResponse
#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"];
...
Da qui in poi avremo disponibile
[RKClient sharedClient]
Monday, May 28, 12
159. Network Layer
Esempio: invio richiesta e visualizzazione risposta
#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.
@implementation MyViewController
...
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad]; resource path
[[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]);
}
Monday, May 28, 12
160. Network Layer
Siamo in grado di
comunicare con un
web service
remoto, inviare
richieste e
processare
risposte,
?
Web Service payload
Monday, May 28, 12
161. Object Mapping
Quando ne abbiamo bisogno e che cosa è?
Quando si ha necessità, non solo di scambiare dati, ma di
rappresentare oggetti.
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.
Punto di forza di RestKit
Monday, May 28, 12
162. Object Mapping
RKObjectManager RKObjectMapping
RKObjectMapper RKObjectMappingProvider
Le operazioni di mapping sono eseguite:
•Quando carichiamo un risorsa remota tramite un’istanza di RKObjectManager
•Quando un oggetto locale è inviato al backend per essere processato
Monday, May 28, 12
163. Object Mapping
Il protagonista principale di questo layer è RKObjectManager
“RKObjectManager è la classe che si occupa della trasformazione
dei dati contenuti nel payload in oggetti”
RKObjectManager
RKClient
App
Monday, May 28, 12
164. Object Mapping
Esempio: caricare oggetti remoti in oggetti locali
Obiettivo: vogliamo recuperare una collection di question
dal web service
Monday, May 28, 12
165. Object Mapping
Esempio: 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
166. Object Mapping
Esempio: caricare oggetti remoti in oggetti locali
...lato client, questi dati sono rappresentati
da una classe
@interface Question : NSObject
@property (nonatomic, copy) NSNumber* identifier;
@property (nonatomic, copy) NSString* body;
@property (nonatomic, copy) NSNumber* correctIdAnswer;
@end
Monday, May 28, 12
167. Object Mapping
Un esempio: caricare oggetti remoti in oggetti locali
Configuriamo RestKit Definiamo un
mapping per
la classe
RKObjectManager* objectManager = [RKObjectManager Question
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"];
Istruiamo il mapping provider ad
usare questionMapping se incontra un
@”questions” key path
Monday, May 28, 12
168. Object Mapping
Un esempio: caricare oggetti remoti in oggetti locali
Carichiamo gli oggetti
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:@”/
questions" delegate:self];
...i dati vengono recuperati, parserizzati e assegnati agli oggetti locali
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:
(NSArray*)objects
{ La classe deve implementare
RKObjectLoaderDelegate
! NSLog(@"Loaded statuses: %@", objects);
}
Monday, May 28, 12
169. Object Mapping
Siamo in grado di Caricare
comunicare con un rappresentazioni di
web service oggetti remoti
remoto, inviare nella nostra App e
richieste e mapparli in oggeti
processare risposte locali
Monday, May 28, 12
170. Object Mapping
JSON
XML
...
Server payload
Inviare oggetti al
server
(Serialization)
Monday, May 28, 12
171. Object Mapping
Serialization? Un’altra operazione di mapping.
RKObjectSerializer RKParser
[{ "body" : "Che cosa si
intende per scope creep?",
Mapping Encoder "correctIdAnswer" : 1,
"identifier" : 1
attributi e
Request
},
relazioni
{ "body" : "Che differenza
Local Domain Intermediate c’è tra lead e lag?", Backend
Objects Dictionary
"correctIdAnswer" : 2,
"identifier" : 2
System
(NSMutableDictionary)
JSON
(XML, URL Form Encode...)
Monday, May 28, 12
172. Object Mapping
Un esempio: inviare oggetti locale al server remoto
Configuriamo RestKit
[[RKObjectManager sharedManager].router routeClass:[Question class]
toResourcePath:@"/questions"
forMethod:RKRequestMethodPOST]; Lo stesso mapping
definito prima è
utilizzo per
[[RKObjectManager sharedManager] serializzare la classe
setSerializationMIMEType:RKMIMETypeJSON];
RKObjectMapping* questionSerializationMapping = [questionMapping
inverseMapping];
[[RKObjectManager sharedManager].mappingProvider
setSerializationMapping:questionSerializationMapping forClass:
[Question class]];
Istruiamo il mapping provider
ad usare
questionSerializationMapping
Monday, May 28, 12
173. Object Mapping
Un esempio: inviare oggetti locale al server remoto
Creiamo l’oggetto
// Create a new Question and POST it to the server
Question* question = [Question new];
question.body = @"Cosa si intende per approccio agile ad un
progetto?";
question.identifier = [NSNumber numberWithInt: 3];
Inviamo la richiesta...
[[RKObjectManager sharedManager] postObject:question delegate:self];
RestKit sa che deve
...recuperiamo la risposta dal server serializzare quando
- (void)objectLoader:(RKObjectLoader*)objectLoader esegue un POST o un
didLoadObjects:(NSArray*)objects PUT
{
! NSLog(@"Loaded statuses: %@", objects);
}
Monday, May 28, 12
174. Routing
Ovvero, dove vivono gli oggetti?
Per interagire con un web service è necessario sapere dove gli oggetti risiedono.
RestKit offre un sistema di routing capace di generare resource path per un oggetto.
/qu 4
est ns/65
ion
s/7 esti o
89 /qu
RKObjectRouter Routing
System /qu
e sti
on
s/1
23
RKObjectRouter registra un mapping tra una classe
del dominio e un resource path per uno specifico
metodo HTTP.
Monday, May 28, 12
175. Routing
Ovvero, dove vivono gli oggetti?
GET
[[RKObjectManager sharedManager].router routeClass:[Question class]
toResourcePath:@"/questions/(idpk)" forMethod:RKRequestMethodGET];
POST
[[RKObjectManager sharedManager].router routeClass:[Question class]
toResourcePath:@"/questions" forMethod:RKRequestMethodPOST];
PUT
[[RKObjectManager sharedManager].router routeClass:[Question class]
toResourcePath:@"/questions/(idpk)" forMethod:RKRequestMethodPUT];
DELETE
[[RKObjectManager sharedManager].router routeClass:[Question class]
toResourcePath:@"/questions/(idpk)" forMethod:RKRequestMethodDELETE];
Monday, May 28, 12
176. Routing
Un esempio: inviare un oggetto al server
Definiamo
default route che
sarà usato per
tutti gli HTTP
Inizializziamo il nostro route... verbs (GET, POST,
PUT e DELETE)
[[RKObjectManager sharedManager].router routeClass:[Question
class] toResourcePath:@"/questions/(identifier)"];
[[RKObjectManager sharedManager].router routeClass:[Question class]
toResourcePath:@"/questions" forMethod:RKRequestMethodPOST];
registriamo
uno specifico
route per il verbo
POST
Monday, May 28, 12
177. Routing
Un esempio: inviare oggetti locale al server remoto
RKObjectRouter è quindi utilizzato per generare resource path quando
utilizziamo getObject, deleteObject, postObject e putObject.
POST
// 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];
“/questions”
Monday, May 28, 12
178. Routing
Un esempio: inviare oggetti locale al server remoto
RKObjectRouter è quindi utilizzato per generare resource path quando
utilizziamo getObject, deleteObject, postObject e putObject.
PUT
Question *question = [Question new];
question.body = @"Che cosa si intende per scope creep?";
question.identifier = [NSNumber numberWithInt: 3];
[[RKObjectManager sharedManager] putObject:question delegate:self];
“/questions/3”
Monday, May 28, 12
179. Routing
Un esempio: inviare oggetti locale al server remoto
RKObjectRouter è quindi utilizzato per generare resource path quando
utilizziamo getObject, deleteObject, postObject e putObject.
DELETE
Question *question = [Question new];
question.identifier = [NSNumber numberWithInt: 3];
[[RKObjectManager sharedManager] deleteObject:question delegate:self];
“/questions/3”
Monday, May 28, 12
180. Offline :|
Core Data Integration
A questo punto, cosa siamo in grado di fare?
Interagire con il Rappresentare Modificare e
web service le risorse inviare oggetti
remoto remote in locali al backend
locale
Monday, May 28, 12
181. Offline :|
Core Data Integration
Assenza di connettività?
Monday, May 28, 12
182. Offline :)
Core Data Integration
Assenza di connettività?
Persistiamo i dati in locale con Core Data
Monday, May 28, 12
183. Offline
Core Data Integration
Vediamo come fare passo dopo passo.
RKManagedObjectStore RKManagedObjectMapping
Setup RestKit
RKObjectManager* objectManager = [RKObjectManager
objectManagerWithBaseURL:@”http://pragmamark.org];
objectManager.objectStore = [RKManagedObjectStore
objectStoreWithStoreFilename:@”Quiz.sqlite];
1
Indicare lo store
Monday, May 28, 12
184. Offline
Core Data Integration
Vediamo come fare passo dopo passo.
2
Mapping Utilizzare RKManagedObjectMapping
RKManagedObjectMapping* questionMapping = [RKManagedObjectMapping
mappingForClass:[Question class]]; Questo permette al 3
Mapper di discriminare tra
questionMapping.primaryKeyAttribute = @"identifier"; oggetti nuovi, aggiornati o
eliminati
[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
185. Offline
Core Data Integration
4
Il modello
persistente deve
ereditare da
NSManagedObject
@interface Question : NSManagedObject
@property (nonatomic, copy) NSNumber* identifier;
@property (nonatomic, copy) NSString* body;
@property (nonatomic, copy) NSNumber* correctIdAnswer;
@end
Monday, May 28, 12
187. Offline
Core Data Integration
6
Data Model Data Model resource
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?'
Monday, May 28, 12
188. Offline
Core Data Integration
Ora che succede? Transient
{questions: [ objects
{ "body" : "Che cosa si
intende per scope creep?",
"correctIdAnswer" : 1,
"identifier" : 1
}, Local Domains
{ "body" : "Che differenza mapping Objects
c’è tra lead e lag?",
"correctIdAnswer" : 2,
"identifier" : 2 Persistent
}]
}
objects
JSON
(XML, Form URL Encode...)
Monday, May 28, 12
189. Offline
Core Data Integration
Un esempio: chiedere i dati al server
Dopo aver fatto richieste al server...
[[RKObjectManager sharedManager]
loadObjectsAtResourcePath:@”/questions" delegate:self];
...i dati sono recuperati, parserizzati e assegnati agli oggetti locali
- (void)objectLoader:(RKObjectLoader*)objectLoader
didLoadObjects:(NSArray*)objects
{
! NSLog(@"Loaded questions: %@", objects);
}
Monday, May 28, 12
190. Offline
Core Data Integration
Un esempio: chiedere i dati al server
2012-05-13 16:01:03.478 WhyMCA[9935:fb03] Loaded questions: (
"<Question: 0x83a1bd0>",
"<Question: 0x83a57d0>"
)
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>)",
}
Monday, May 28, 12
191. Offline
Core Data Integration
Un esempio: chiedere i dati al server
Impostiamo la nostra tecnica
if ([[RKObjectManager sharedManager] isOnline])
{
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/
questions" delegate:self];
}
else
{
NSArray *questions = [Question allObjects];
}
Alternative?
•Implementare di RKManagedObjectCache protocol
•Utilizzare RKRequestCache
•Database seeding
Monday, May 28, 12
192. In practice
RestKit Mapping & CoreData
“Non sempre le risposte del web service sono
come ce le aspettiamo”(Anonimo)
Team Mobile Team Server-side
Monday, May 28, 12
193. In practice
RestKit Mapping & CoreData
Elaboriamo un pò il nostro model
•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”
Monday, May 28, 12
194. In practice
RestKit Mapping & CoreData
Dove è la key @“questions” ?
{[
Come identifichiamo il contenuto?
{"_id": {
"$identifier": "4faf69fee4b0895a3ed9b1ff"
},
{ “questions”: [
"correctIdAnswer": 1,
{ "identifier" : 1 "body": "Quale è il significato del termine
"body" : "Che cosa si intende per scope creep?", lead?",
"correctIdAnswer" : 1, "answers": [
}, {
"identifier": "3",
{ "identifier" : 2
"body": "risposta B"
"body" : "Che differenza c’è tra lead e lag?", },
"correctIdAnswer" : 2, {
}] "identifier": "1",
} "body": "risposta A"
}
]
},
{...
Monday, May 28, 12
197. In practice
RestKit 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
198. In practice
RestKit Mapping & CoreData
Possiamo costruire un mapping dinamicamente...
[[RKObjectManager sharedManager] postObject:question delegate:self
block:^(RKObjectLoader* loader) {
loader.objectMapping = [RKObjectMapping mappingForClass:
[Question class] block:^(RKObjectMapping* mapping) {
[mapping mapAttributes:@"identifier", @"body", nil];
}];
}];
Monday, May 28, 12
199. Le code i retroscena.
Inviare richieste e processare risposte:
RKRequest
RKResponse
RKClient
Payload
Monday, May 28, 12
200. Le code i retroscena.
Inviare richieste e processare risposte:
RKRequest
RKResponse
RKClient
Payload
RKRequestQueue
Monday, May 28, 12
201. Le code i retroscena.
Inviare richieste e processare risposte:
Cosa succede quando inviamo una richiesta con RKRequest?
[RKClient sharedClient].requestQueue
//[[RKClient sharedClient].requestQueue addRequest:loader];
RKRequestQueue è utilizzato anche per:
•rilevare connettività
•limitare le richieste concorrenti
•eliminare richieste per un determinato delegato
[[RKClient sharedClient].requestQueue
cancelRequestsWithDelegate:delegate];
Monday, May 28, 12
202. Le code i retroscena.
Inviare richieste e processare risposte:
Possiamo usarle per:
•Raggruppare le chiamate per la paginazione, per la
ricerca, per il workflow di acquisto, etc.. e utilizzare la
sharedQueue per soddisfare la user action.
•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.
Monday, May 28, 12
203. Le code
Inviare richieste e processare risposte: i retroscena.
Creare una coda...
RKRequestQueue *queue = [RKRequestQueue
requestQueueWithName:nameQueue];
queue.concurrentRequestsLimit = 5;
Monday, May 28, 12
205. Le code
Inviare richieste e processare risposte: i retroscena.
Svuotare la coda...
//verifica prima se esiste la queue
BOOL 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]);
}
Monday, May 28, 12