SlideShare a Scribd company logo
iOS Api Client
                               Soluzioni a confronto




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


Monday, May 28, 12
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
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
Disclaimer


        • Non è una sessione su REST
        • Non è una sessione su sulle API Server
        • Non vuole essere una sessione esauriente


Monday, May 28, 12
Agenda


        • Architettura
        • Framework custom
        • Framework terze parti: REST Kit


Monday, May 28, 12
Scenari




Monday, May 28, 12
Scenari

        • Scenario A
                Server Api non REST(ful)




Monday, May 28, 12
Scenari

        • Scenario A
                Server Api non REST(ful)
        • Scenario B
                Server API REST(ful)




Monday, May 28, 12
Soluzioni




Monday, May 28, 12
Soluzioni

        A. Easy (w lo spaghetti code!)




Monday, May 28, 12
Soluzioni

        A. Easy (w lo spaghetti code!)
        B. Framework custom




Monday, May 28, 12
Soluzioni

        A. Easy (w lo spaghetti code!)
        B. Framework custom
        C. Framework di terze parti




Monday, May 28, 12
Un nuovo progetto




Monday, May 28, 12
Un nuovo progetto




Monday, May 28, 12
Un nuovo progetto
                           •   App per la N.A.S.A.




Monday, May 28, 12
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
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
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
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
Dominio
                              1   n           1   n
                     Planet           Rover           Cam

                                         1

                                         1

                                      Geo




Monday, May 28, 12
Server

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

        •      RESPONSE
               content-type: text/html




Monday, May 28, 12
Server

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

        •      RESPONSE
               content-type: text/html




Monday, May 28, 12
Non ci REST che piang!




Monday, May 28, 12
Non ci REST che piang!




Monday, May 28, 12
Non ci REST che piang!


                           Accettiamo la sfida!




Monday, May 28, 12
Soluzione B
                     sviluppiamo un framework custom




Monday, May 28, 12
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
Architettura
                      un approccio graduale




Monday, May 28, 12
Layers




Monday, May 28, 12
Layers
                      View




Monday, May 28, 12
Layers
                       View
                     Controller




Monday, May 28, 12
Layers
                         View
                      Controller




                     Network Layer



Monday, May 28, 12
Layers
                         View
                      Controller

                         Domain
                         Model
                          Layer


                     Network Layer



Monday, May 28, 12
Layers
                         View
                      Controller

                         Domain
                                     Data
                         Model
                                     Layer
                          Layer


                     Network Layer



Monday, May 28, 12
Layers
                                  View
                                Controller

                                  Domain
                     Business                Data
                                  Model
                      Layer                  Layer
                                   Layer


                            Network Layer



Monday, May 28, 12
Layers
                                  View
                                Controller

                                  Domain
                     Business                Data
                                  Model
                      Layer                  Layer
                                   Layer


                            Network Layer



Monday, May 28, 12
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
Network Layer
                     il primo mattoncino della nostra architettura




Monday, May 28, 12
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
Request




Monday, May 28, 12
Request

                               Network Layer


                     Request




Monday, May 28, 12
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
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
Monday, May 28, 12
NSURLConnection




Monday, May 28, 12
NSURLConnection
          Pro




Monday, May 28, 12
NSURLConnection
          Pro
              • Nativo




Monday, May 28, 12
NSURLConnection
          Pro
              • Nativo
              • Documentato




Monday, May 28, 12
NSURLConnection
          Pro
              • Nativo
              • Documentato
              • Flessibile




Monday, May 28, 12
NSURLConnection
          Pro
              • Nativo
              • Documentato
              • Flessibile




Monday, May 28, 12
NSURLConnection
          Pro
              • Nativo
              • Documentato
              • Flessibile




Monday, May 28, 12
NSURLConnection
          Pro                 Contro
              • Nativo
              • Documentato
              • Flessibile




Monday, May 28, 12
NSURLConnection
          Pro                 Contro
              • Nativo        • Povero
              • Documentato
              • Flessibile




Monday, May 28, 12
NSURLConnection
          Pro                 Contro
              • Nativo        • Povero
              • Documentato   • Verboso
              • Flessibile




Monday, May 28, 12
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
ASIHTTPRequest

        • Mac OS X & iPhone
        • Synchronous & asynchronous requests
        • Basic, Digest e NTLM authentication
        • Cache control and ETag support
        • Throttling bandwidth

Monday, May 28, 12
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
AFNetworking

        • HTTP Requests (cancelled, suspended / resumed)
        • Authenticating requests with HTTP Basic
                credentials or an OAuth token
        • Blocks
        • feature-rich APIs

Monday, May 28, 12
AFNetworkig
    NSURL *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
Response

                     Network Layer




Monday, May 28, 12
Response

                     Network Layer




Monday, May 28, 12
Response

                               Network Layer


                     Request




Monday, May 28, 12
Response

                               Network Layer


                     Request    Response




Monday, May 28, 12
Response

                               Network Layer


                     Request    Response




Monday, May 28, 12
Response

                               Network Layer


                     Request    Response




Monday, May 28, 12
Response

                               Network Layer


                     Request    Response




Monday, May 28, 12
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
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
Parser


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




Monday, May 28, 12
JSON Parser
           Alcune librerie
                     • NSJSONSerialization
                     • JSONKit
                     • SBJson
           Benckmarks
           https://github.com/samsoffes/json-benchmarks


Monday, May 28, 12
XML Parser
           Alcune 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
Cache

                     Network Layer




Monday, May 28, 12
Cache

                     Network Layer




Monday, May 28, 12
Cache

                               Network Layer


                     Request




Monday, May 28, 12
Cache

                               Network Layer


                     Request    Response




Monday, May 28, 12
Cache

                               Network Layer


                     Request    Response   Cache




Monday, May 28, 12
Cache

                               Network Layer


                     Request    Response   Cache




Monday, May 28, 12
Cache

                               Network Layer


                     Request    Response   Cache




Monday, May 28, 12
Cache

           Cosa deve fare
              • Gestire la direttiva cache-control
              • Gestire la direttiva ETag
              • Storage policy: per session o permanent


Monday, May 28, 12
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
Client

                     Network Layer




Monday, May 28, 12
Client

                     Network Layer




Monday, May 28, 12
Client

                               Network Layer


                     Request




Monday, May 28, 12
Client

                               Network Layer


                     Request    Response




Monday, May 28, 12
Client

                               Network Layer


                     Request    Response   Cache




Monday, May 28, 12
Client

                               Network Layer


                     Request    Response   Cache   Client




Monday, May 28, 12
Client

                               Network Layer


                     Request    Response   Cache   Client




Monday, May 28, 12
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
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
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
Network Manager

                         Network Layer




Monday, May 28, 12
Network Manager

                                 Network Layer


                       Request




Monday, May 28, 12
Network Manager

                                 Network Layer


                       Request    Response




Monday, May 28, 12
Network Manager

                                 Network Layer


                       Request    Response   Cache




Monday, May 28, 12
Network Manager

                                 Network Layer


                       Request    Response   Cache   Client




Monday, May 28, 12
Network Manager

                                 Network Layer
                                 Network Manager

                       Request    Response   Cache   Client




Monday, May 28, 12
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
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
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
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
Network Layer




Monday, May 28, 12
Network Layer
          In conclusione

              •      HTTP Request & Response

              •      Tunneling SSH/VPN

              •      Ambienti (stage, produzione
                     etc.)

              •      Cache (HTTP)

              •      Network Manager



Monday, May 28, 12
Network Layer
          In conclusione

              •      HTTP Request & Response

              •      Tunneling SSH/VPN

              •      Ambienti (stage, produzione
                     etc.)

              •      Cache (HTTP)

              •      Network Manager



Monday, May 28, 12
One more thing...




Monday, May 28, 12
One more thing...




Monday, May 28, 12
One more thing...


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




Monday, May 28, 12
Domain Model Layer
                        modelliamo il nostro business




Monday, May 28, 12
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
Model

                     Domain Model Layer




Monday, May 28, 12
Model

                     Domain Model Layer




Monday, May 28, 12
Model

                     Domain Model Layer


                     Model




Monday, May 28, 12
Model

                     Domain Model Layer


                     Model




Monday, May 28, 12
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
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
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
Mapper

                     Domain Model Layer




Monday, May 28, 12
Mapper

                     Domain Model Layer




Monday, May 28, 12
Mapper

                     Domain Model Layer


                     Model




Monday, May 28, 12
Mapper

                     Domain Model Layer


                     Model        Mapper




Monday, May 28, 12
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
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
Domain Model




Monday, May 28, 12
Domain Model

          In conclusione

              •      Entità e relazioni

              •      Mappatura




Monday, May 28, 12
Domain Model

          In conclusione

              •      Entità e relazioni

              •      Mappatura




Monday, May 28, 12
One more “little” thing




Monday, May 28, 12
One more “little” thing




Monday, May 28, 12
One more “little” thing


                              “L’applicazione deve
                              funzionare anche
                              OFFLINE”




Monday, May 28, 12
Data Layer
                     persistiamo i nostri dati




Monday, May 28, 12
Data Layer

           Cosa deve fare
              • Persistere le informazioni
              • Recuperare le informazioni


Monday, May 28, 12
Store

                     Data Layer




Monday, May 28, 12
Store

                     Data Layer




Monday, May 28, 12
Store

                             Data Layer


                     Store




Monday, May 28, 12
Store

                             Data Layer


                     Store




Monday, May 28, 12
File system

        • File system
                NSCoding, NSKeyedArchiver, NSKeyedUnarchiver


        • Plist
                NSDictionary, NSArray, NSFileManager




Monday, May 28, 12
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
Manager

                      Data Layer




Monday, May 28, 12
Manager

                      Data Layer




Monday, May 28, 12
Manager

                             Data Layer


                     Store




Monday, May 28, 12
Manager

                             Data Layer


                     Store            Manager




Monday, May 28, 12
Manager

           Cosa deve fare
              • Fornire un’interfaccia di accesso ai dati persistiti
              • Fornire strumenti di interrogazione


Monday, May 28, 12
Conclusioni
                        e quindi?




Monday, May 28, 12
Framework custom
                        Layer            Quando


                     Network Layer       SEMPRE


                     Domain Model    Leggere e scrivere


                      Data Layer          Offline



Monday, May 28, 12
Framework custom




Monday, May 28, 12
Framework custom

           Vantaggi




Monday, May 28, 12
Framework custom

           Vantaggi
              • Know-how




Monday, May 28, 12
Framework custom

           Vantaggi
              • Know-how
              • Modulare



Monday, May 28, 12
Framework custom

           Vantaggi
              • Know-how
              • Modulare
              • Flessibile (Business)


Monday, May 28, 12
Framework custom

           Vantaggi                     Svantaggi
              • Know-how
              • Modulare
              • Flessibile (Business)


Monday, May 28, 12
Framework custom

           Vantaggi                     Svantaggi
              • Know-how                • Tempo (Costi)
              • Modulare
              • Flessibile (Business)


Monday, May 28, 12
Framework custom

           Vantaggi                     Svantaggi
              • Know-how                • Tempo (Costi)
              • Modulare                • Skill
              • Flessibile (Business)


Monday, May 28, 12
Framework custom

           Vantaggi                     Svantaggi
              • Know-how                • Tempo (Costi)
              • Modulare                • Skill
              • Flessibile (Business)   • Declinato


Monday, May 28, 12
Soluzione C

                                     API +

                       Dominio di Business =




Monday, May 28, 12
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
RestKit
                           Che cosa fa ?

 HTTP PROTOCOL
  REST SOAP XML
   ENCODE PARSER
      CODE ACTIVE RECORD
       PATTERN MAPPING
   CACHE STRATEGY SQL




Monday, May 28, 12
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
Network Layer
                                                                Base URL
                            RKClient
                     Http headers - Type Authentication




                                                          RKClient



                                         App

Monday, May 28, 12
Network Layer
                                                                Base URL
                            RKClient
                     Http headers - Type Authentication




                                                               Base URL
                            RKClient
                     Http headers - Type Authentication




                                                          RKClient



                                         App

Monday, May 28, 12
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
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
Network Layer
                            Siamo in grado di
                           comunicare con un
                               web service
                             remoto, inviare
                               richieste e
                               processare
                                risposte,




                                                ?
                     Web Service                payload

Monday, May 28, 12
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
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
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
Object Mapping
                     Esempio: caricare oggetti remoti in oggetti locali




  Obiettivo: vogliamo recuperare una collection di question
                       dal web service




Monday, May 28, 12
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
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
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
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
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
Object Mapping
                                         JSON
                                          XML
                                           ...
                     Server               payload

                              Inviare oggetti al
                                    server
                                (Serialization)




Monday, May 28, 12
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
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
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
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
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
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
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
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
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
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
Offline :|
                        Core Data Integration

                     Assenza di connettività?




Monday, May 28, 12
Offline :)
                               Core Data Integration

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




Monday, May 28, 12
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
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
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
Offline
                         Core Data Integration


      @implementation Question       @implementation Question

      @synthesize identifier;        @dynamic identifier;
      @synthesize body;              @dynamic body;
      @synthesize correctIdAnswer;   @dynamic correctIdAnswer;
                                                           5
      @end                           @end    @dynamic vs
                                             @synthesize




Monday, May 28, 12
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
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
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
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
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
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
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
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
In practice
                             RestKit 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

  @interface Answer : NSManagedObject

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

  @end




Monday, May 28, 12
In practice
                     RestKit Mapping & CoreData
//Mapping
RKManagedObjectMapping* 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
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
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
Le code i retroscena.
                     Inviare richieste e processare risposte:

              RKRequest
                                               RKResponse




                          RKClient




                                     Payload




Monday, May 28, 12
Le code i retroscena.
                     Inviare richieste e processare risposte:

              RKRequest
                                               RKResponse




                          RKClient




                                     Payload




                                                            RKRequestQueue



Monday, May 28, 12
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
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
Le code
                 Inviare richieste e processare risposte: i retroscena.


    Creare una coda...
   RKRequestQueue *queue = [RKRequestQueue
   requestQueueWithName:nameQueue];

   queue.concurrentRequestsLimit = 5;




Monday, May 28, 12
Le code
                 Inviare richieste e processare risposte: i retroscena.


  Aggiungere richieste...
 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];




Monday, May 28, 12
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
Conclusioni
                        e quindi?




Monday, May 28, 12
“Buon senso”



Monday, May 28, 12

More Related Content

Featured

2024 Trend Updates: What Really Works In SEO & Content Marketing
2024 Trend Updates: What Really Works In SEO & Content Marketing2024 Trend Updates: What Really Works In SEO & Content Marketing
2024 Trend Updates: What Really Works In SEO & Content Marketing
Search Engine Journal
 
Storytelling For The Web: Integrate Storytelling in your Design Process
Storytelling For The Web: Integrate Storytelling in your Design ProcessStorytelling For The Web: Integrate Storytelling in your Design Process
Storytelling For The Web: Integrate Storytelling in your Design Process
Chiara Aliotta
 
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
OECD Directorate for Financial and Enterprise Affairs
 
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
SocialHRCamp
 
2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
Marius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
Expeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
Skeleton Technologies
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
Rajiv Jayarajah, MAppComm, ACC
 

Featured (20)

2024 Trend Updates: What Really Works In SEO & Content Marketing
2024 Trend Updates: What Really Works In SEO & Content Marketing2024 Trend Updates: What Really Works In SEO & Content Marketing
2024 Trend Updates: What Really Works In SEO & Content Marketing
 
Storytelling For The Web: Integrate Storytelling in your Design Process
Storytelling For The Web: Integrate Storytelling in your Design ProcessStorytelling For The Web: Integrate Storytelling in your Design Process
Storytelling For The Web: Integrate Storytelling in your Design Process
 
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
 
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
 
2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 

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
  • 5. Agenda • Architettura • Framework custom • Framework terze parti: REST Kit Monday, May 28, 12
  • 7. Scenari • Scenario A Server Api non REST(ful) Monday, May 28, 12
  • 8. Scenari • Scenario A Server Api non REST(ful) • Scenario B Server API REST(ful) Monday, May 28, 12
  • 10. Soluzioni A. Easy (w lo spaghetti code!) Monday, May 28, 12
  • 11. Soluzioni A. Easy (w lo spaghetti code!) B. Framework custom Monday, May 28, 12
  • 12. Soluzioni A. Easy (w lo spaghetti code!) B. Framework custom C. Framework di terze parti Monday, May 28, 12
  • 15. Un nuovo progetto • App per la N.A.S.A. 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
  • 23. Non ci REST che piang! Monday, May 28, 12
  • 24. Non ci REST che piang! 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
  • 30. Layers View Monday, May 28, 12
  • 31. Layers View Controller 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
  • 43. 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
  • 46. NSURLConnection Pro Monday, May 28, 12
  • 47. NSURLConnection Pro • Nativo 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
  • 57. 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
  • 58. AFNetworking • HTTP Requests (cancelled, suspended / resumed) • Authenticating requests with HTTP Basic credentials or an OAuth token • Blocks • feature-rich APIs Monday, May 28, 12
  • 59. AFNetworkig NSURL *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
  • 60. Response Network Layer Monday, May 28, 12
  • 61. Response Network Layer 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
  • 68. 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
  • 69. Parser Cosa deve fare • Trasformare stringhe o dati binari in strutture dati native (es. da JSon a NSArray). Monday, May 28, 12
  • 70. JSON Parser Alcune librerie • NSJSONSerialization • JSONKit • SBJson Benckmarks https://github.com/samsoffes/json-benchmarks Monday, May 28, 12
  • 71. XML Parser Alcune 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
  • 72. Cache Network Layer Monday, May 28, 12
  • 73. Cache Network Layer Monday, May 28, 12
  • 74. Cache Network Layer Request Monday, May 28, 12
  • 75. Cache Network Layer Request Response Monday, May 28, 12
  • 76. Cache Network Layer Request Response Cache Monday, May 28, 12
  • 77. Cache Network Layer Request Response Cache Monday, May 28, 12
  • 78. Cache Network Layer Request Response Cache 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
  • 81. Client Network Layer Monday, May 28, 12
  • 82. Client Network Layer Monday, May 28, 12
  • 83. Client Network Layer Request Monday, May 28, 12
  • 84. Client Network Layer Request Response Monday, May 28, 12
  • 85. Client Network Layer Request Response Cache Monday, May 28, 12
  • 86. Client Network Layer Request Response Cache Client Monday, May 28, 12
  • 87. Client Network Layer Request Response Cache Client 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
  • 90. 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
  • 91. Network Manager Network Layer Monday, May 28, 12
  • 92. Network Manager Network Layer Request Monday, May 28, 12
  • 93. Network Manager Network Layer Request Response Monday, May 28, 12
  • 94. Network Manager Network Layer Request Response Cache Monday, May 28, 12
  • 95. Network Manager Network Layer Request Response Cache Client Monday, May 28, 12
  • 96. Network Manager Network Layer Network Manager Request Response Cache Client 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
  • 99. 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
  • 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
  • 102. Network Layer In conclusione • HTTP Request & Response • Tunneling SSH/VPN • Ambienti (stage, produzione etc.) • Cache (HTTP) • Network Manager Monday, May 28, 12
  • 103. Network Layer In conclusione • HTTP Request & Response • Tunneling SSH/VPN • Ambienti (stage, produzione etc.) • Cache (HTTP) • Network Manager Monday, May 28, 12
  • 106. One more thing... “Oltre che leggere l’app deve poter anche inviare dei comandi al rover!” Monday, May 28, 12
  • 107. Domain Model Layer modelliamo il nostro business 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
  • 109. Model Domain Model Layer Monday, May 28, 12
  • 110. Model Domain Model Layer 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
  • 114. 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
  • 115. 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
  • 116. Mapper Domain Model Layer Monday, May 28, 12
  • 117. Mapper Domain Model Layer 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
  • 121. 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
  • 123. Domain Model In conclusione • Entità e relazioni • Mappatura Monday, May 28, 12
  • 124. Domain Model In conclusione • Entità e relazioni • Mappatura Monday, May 28, 12
  • 125. One more “little” thing Monday, May 28, 12
  • 126. One more “little” thing Monday, May 28, 12
  • 127. One more “little” thing “L’applicazione deve funzionare anche OFFLINE” Monday, May 28, 12
  • 128. Data Layer persistiamo i nostri dati Monday, May 28, 12
  • 129. Data Layer Cosa deve fare • Persistere le informazioni • Recuperare le informazioni Monday, May 28, 12
  • 130. Store Data Layer Monday, May 28, 12
  • 131. Store Data Layer Monday, May 28, 12
  • 132. Store Data Layer Store Monday, May 28, 12
  • 133. Store Data Layer Store Monday, May 28, 12
  • 134. File system • File system NSCoding, NSKeyedArchiver, NSKeyedUnarchiver • Plist NSDictionary, NSArray, NSFileManager Monday, May 28, 12
  • 135. 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
  • 136. Manager Data Layer Monday, May 28, 12
  • 137. Manager Data Layer Monday, May 28, 12
  • 138. Manager Data Layer Store Monday, May 28, 12
  • 139. Manager Data Layer Store Manager Monday, May 28, 12
  • 140. Manager Cosa deve fare • Fornire un’interfaccia di accesso ai dati persistiti • Fornire strumenti di interrogazione Monday, May 28, 12
  • 141. Conclusioni e quindi? Monday, May 28, 12
  • 142. Framework custom Layer Quando Network Layer SEMPRE Domain Model Leggere e scrivere Data Layer Offline Monday, May 28, 12
  • 144. Framework custom Vantaggi Monday, May 28, 12
  • 145. Framework custom Vantaggi • Know-how Monday, May 28, 12
  • 146. Framework custom Vantaggi • Know-how • Modulare Monday, May 28, 12
  • 147. Framework custom Vantaggi • Know-how • Modulare • Flessibile (Business) Monday, May 28, 12
  • 148. Framework custom Vantaggi Svantaggi • Know-how • Modulare • Flessibile (Business) Monday, May 28, 12
  • 149. Framework custom Vantaggi Svantaggi • Know-how • Tempo (Costi) • Modulare • Flessibile (Business) Monday, May 28, 12
  • 150. Framework custom Vantaggi Svantaggi • Know-how • Tempo (Costi) • Modulare • Skill • Flessibile (Business) Monday, May 28, 12
  • 151. Framework custom Vantaggi Svantaggi • Know-how • Tempo (Costi) • Modulare • Skill • Flessibile (Business) • Declinato 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
  • 186. Offline Core Data Integration @implementation Question @implementation Question @synthesize identifier; @dynamic identifier; @synthesize body; @dynamic body; @synthesize correctIdAnswer; @dynamic correctIdAnswer; 5 @end @end @dynamic vs @synthesize 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
  • 195. In practice RestKit 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 @interface Answer : NSManagedObject @property (nonatomic, copy) NSString* identifier; @property (nonatomic, copy) NSString* body; @property (nonatomic, retain) NSSet* questions; @end Monday, May 28, 12
  • 196. In practice RestKit Mapping & CoreData //Mapping RKManagedObjectMapping* 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
  • 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
  • 204. Le code Inviare richieste e processare risposte: i retroscena. Aggiungere richieste... 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]; 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
  • 206. Conclusioni e quindi? Monday, May 28, 12