Dal punto di vista dello sviluppatore, uno dei cambiamenti più significativi in iOS 7 e OS X Mavericks è l'introduzione di NSURLSession
. Nonostante NSURLSession
può sembrare scoraggiante a prima vista, è importante che tu capisca di cosa si tratta, in che modo si relaziona NSURLConnection
, e quali sono le differenze. In questa serie, ti illustrerò i fondamenti di NSURLSession
così puoi sfruttare questa nuova tecnologia nelle tue applicazioni.
NSURLConnection
?La prima domanda che potresti chiederti è perché Apple ha ritenuto necessario presentare NSURLSession
mentre siamo perfettamente soddisfatti NSURLConnection
. La vera domanda è se tu siamo felice con NSURLConnection
. Ti ricordi quella volta in cui ti stavi maledicendo e lanciando cose NSURLConnection
? La maggior parte degli sviluppatori di Cocoa sono stati in quel luogo, motivo per cui Apple ha deciso di tornare al tavolo da disegno e creare una soluzione più elegante, più adatta per il web moderno.
Nonostante NSURLSession
e NSURLConnection
hanno molto in comune in termini di come funzionano, a un livello fondamentale, sono molto diversi. Apple ha creato NSURLSession
per assomigliare ai concetti generali di NSURLConnection
, ma imparerai nel corso di questa serie NSURLSession
è moderno, più facile da usare e costruito pensando al mobile.
NSURLSession
?Prima di discutere le differenze tra NSURLSession
e NSURLConnection
, è una buona idea prima dare un'occhiata più da vicino a cosa NSURLSession
è. Nonostante il suo nome, NSURLSession
non è solo un'altra classe che puoi usare in un'applicazione iOS o OS X.. NSURLSession
è prima di tutto una tecnologia proprio come NSURLConnection
è.
NSURLSession
e NSURLConnection
entrambi forniscono una API per interagire con vari protocolli, come ad esempio HTTP
e HTTPS
. L'oggetto di sessione, un'istanza di NSURLSession
classe, è ciò che gestisce questa interazione. È un contenitore altamente configurabile con un'API elegante che consente un controllo a grana fine. Offre caratteristiche che sono assenti in NSURLConnection
. Inoltre, con NSURLSession
, puoi svolgere compiti che semplicemente non sono possibili con NSURLConnection
, come l'implementazione della navigazione privata.
L'unità di base del lavoro quando si lavora con NSURLSession
è il compito, un'istanza di NSURLSessionTask
. Esistono tre tipi di attività, attività di dati, carica le attività, e attività di download.
NSURLSessionDataTask
. Le attività dati vengono utilizzate per richiedere dati da un server, come i dati JSON. La principale differenza con le attività di upload e download è che restituiscono i dati direttamente alla tua applicazione anziché passare attraverso il file system. I dati vengono archiviati solo in memoria.NSURLSessionUploadTask
è una sottoclasse di NSURLSessionDataTask
e si comporta in modo simile. Una delle principali differenze con un'attività di dati normale è che le attività di caricamento possono essere utilizzate in una sessione creata con una configurazione di sessione in background.NSURLSessionDownloadTask
, eredita direttamente da NSURLSessionTask
. La differenza più significativa con le attività di dati è che un'attività di download scrive la sua risposta direttamente su un file temporaneo. Questo è abbastanza diverso da un normale task di dati che memorizza la risposta in memoria. È possibile Annulla un'attività di download e curriculum vitae in un secondo momento.Come puoi immaginare, l'asincronicità è un concetto chiave in NSURLSession
. Il NSURLSession
L'API restituisce i dati richiamando un gestore di completamento o tramite il delegato della sessione. L'API di NSURLSession
è stato progettato pensando alla flessibilità, come noterete un po 'più avanti in questo tutorial.
Come ho detto prima, NSURLSession
è sia una tecnologia che una classe con cui lavorerai. Il NSURLSession
API ospita un numero di classi, ma NSURLSession
è il componente chiave che invia richieste e riceve risposte. La configurazione dell'oggetto di sessione, tuttavia, viene gestita da un'istanza di NSURLSessionConfiguration
classe. Il NSURLSessionTask
la classe e le sue tre sottoclassi concrete sono le worker e vengono sempre utilizzate in congiunzione con una sessione in quanto è la sessione che crea gli oggetti task.
Tutti e due NSURLSession
e NSURLConnection
fare molto affidamento sul modello di delega. Il NSURLSessionDelegate
protocollo dichiara una manciata di metodi delegati per la gestione degli eventi a livello di sessione. Inoltre, il NSURLSessionTask
classe e sottoclassi ciascuna dichiarano un protocollo delegato per la gestione degli eventi a livello di attività.
Il NSURLSession
L'API si basa sulle classi con le quali hai già familiarità, ad esempio NSURL
, NSURLRequest
, e NSURLResponse
.
Come fa NSURLSession
differire dalla NSURLConnection
? Questa è una domanda importante, perché NSURLConnection
non viene deprecato da Apple. Puoi ancora usarlo NSURLConnection
nei tuoi progetti. Perché dovresti usare? NSURLSession
?
La prima cosa da capire è che il NSURLSession
istanza è l'oggetto che gestisce la richiesta e la risposta. Questo è simile a come NSURLConnection
funziona, ma la differenza chiave è che la configurazione della richiesta è gestita dall'oggetto session, che è un oggetto longevo. Questo è fatto attraverso il NSURLSessionConfiguration
classe. Non solo fornisce il NSURLSession
Configurazione API a grana fine attraverso il NSURLSessionConfiguration
classe, incoraggia la separazione dei dati (corpo della richiesta) dai metadati. Il NSURLSessionDownloadTask
lo illustra bene scrivendo direttamente la risposta al file system.
L'autenticazione è più semplice e gestita in modo più elegante NSURLSession
. Il NSURLSession
L'API gestisce l'autenticazione in base a una connessione anziché su una base di richiesta, ad esempio NSURLConnection
lo fa. Il NSURLSession
L'API rende inoltre più conveniente fornire opzioni HTTP e ogni sessione può avere un contenitore di memoria separato a seconda di come si configura la sessione.
Nell'introduzione, te l'ho detto NSURLSession
fornisce un'interfaccia moderna, che si integra perfettamente con iOS 7. Un esempio di questa integrazione è NSURLSession
Gli upload e i download fuori processo. NSURLSession
è ottimizzato per preservare la durata della batteria, supporta la pausa, l'annullamento e la ripresa delle attività, nonché l'API multitasking di UIKit. Di cosa non si deve amare NSURLSession
?
Una nuova API è appresa al meglio dalla pratica, quindi è il momento di accendere Xcode e bagnarsi i piedi. Avvia Xcode 5, crea un nuovo progetto selezionando Nuovo> Progetto ... dal File menu e selezionare Applicazione vista singola modello dall'elenco di modelli di applicazioni iOS.
Dai un nome al tuo progetto, dì a Xcode dove vorresti salvarlo e premi Creare. Non è necessario mettere il progetto sotto il controllo del codice sorgente.
Quando si lavora con NSURLSession
, è importante capire che l'oggetto di sessione, un'istanza di NSURLSession
, è il giocatore di stelle. Gestisce le richieste e le risposte, configura le richieste, gestisce l'archiviazione e lo stato delle sessioni, ecc. La creazione di una sessione può essere effettuata in diversi modi. Il modo più rapido per iniziare è quello di utilizzare NSURLSession
'S sharedSession
metodo di classe come mostrato di seguito.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession];
Creare un sessione
oggetto nel controller della vista viewDidLoad
metodo come mostrato sopra. Il sessione
l'oggetto che abbiamo creato va bene per il nostro esempio, ma probabilmente nella maggior parte dei casi desideri un po 'più di flessibilità. Il sessione
l'oggetto che abbiamo appena creato utilizza il globale NSURLCache
, NSHTTPCookieStorage
, e NSURLCredentialStorage
. Ciò significa che funziona in modo abbastanza simile a un'implementazione predefinita di NSURLConnection
.
Mettere il sessione
oggetto da usare, interrogiamo l'API di ricerca di iTunes Store e cerchiamo il software realizzato da Apple. L'API di ricerca di iTunes Store è facile da usare e non richiede autenticazione, il che lo rende ideale per il nostro esempio.
Per eseguire una query sull'API di ricerca, è necessario inviare una richiesta a https://itunes.apple.com/search
e passare alcuni parametri. Come abbiamo visto in precedenza, quando si utilizza il NSURLSession
API, una richiesta è rappresentata da un'attività. Per eseguire una query sull'API di ricerca, tutto ciò di cui abbiamo bisogno è un'attività di dati, un'istanza di NSURLSessionDataTask
classe. Dai un'occhiata al aggiornato viewDidLoad
implementazione mostrata di seguito.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (dati NSData *, risposta NSURLResponse *, errore NSError *) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: opzioni dati: 0 errore: nil]; NSLog (@ "% @", json); ];
Esistono numerosi metodi disponibili per creare un'attività, ma il concetto chiave da comprendere è che il sessione
oggetto esegue l'effettiva creazione e configurazione dell'attività. In questo esempio, invochiamo dataTaskWithURL: completionHandler:
e passargli un'istanza di NSURL
così come un gestore di completamento. Il gestore di completamento accetta tre argomenti, il dati grezzi della risposta (NSData
), il oggetto di risposta (NSURLResponse
), e un oggetto di errore (NSError
). Se la richiesta ha esito positivo, l'oggetto error è zero
. Poiché sappiamo che la richiesta restituisce una risposta JSON, creiamo a Fondazione oggetto dal dati
oggetto che abbiamo ricevuto e registrare l'output sulla console.
È importante capire che il errore
l'oggetto passato al gestore di completamento è solo popolato, non zero
, se la richiesta non è riuscita o si è verificato un errore. In altre parole, se la richiesta ha restituito a 404
risposta, la richiesta è riuscita per quanto riguarda le sessioni. Il errore
l'oggetto sarà quindi zero
. Questo è un concetto importante da comprendere quando si lavora con NSURLSession
e NSURLConnection
per questo motivo.
Costruisci il progetto ed esegui l'applicazione in iOS Simulator o su un dispositivo fisico e ispeziona la console di Xcode. Nulla viene stampato sulla console. Cosa è andato storto? Come ho detto prima, il NSURLSession
L'API supporta la sospensione, l'annullamento e il ripristino di attività o richieste. Questo comportamento è simile a quello di NSOperation
e potrebbe ricordarti la libreria di AFNetworking. Un'attività ha a stato
proprietà che indica se l'attività è in esecuzione (NSURLSessionTaskStateRunning
), sospeso (NSURLSessionTaskStateSuspended
), annullamento (NSURLSessionTaskStateCanceling
), o completato (NSURLSessionTaskStateCompleted
). Quando un oggetto di sessione crea un'attività, l'attività inizia la sua vita nel sospeso stato. Per iniziare l'attività, dobbiamo dirlo a curriculum vitae
a chiamata curriculum vitae
sull'attività. Aggiorna il viewDidLoad
metodo come mostrato di seguito, eseguire l'applicazione ancora una volta e ispezionare l'output nella console. Missione compiuta.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (dati NSData *, risposta NSURLResponse *, errore NSError *) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: opzioni dati: 0 errore: nil]; NSLog (@ "% @", json); ]; [curriculum DataTask];
Nell'esempio precedente, abbiamo utilizzato un gestore di completamento per elaborare la risposta ricevuta dalla richiesta. È anche possibile ottenere lo stesso risultato implementando i protocolli delegati dell'attività. Vediamo cosa serve per scaricare un'immagine sfruttando NSURLSession
e il NSURLSessionDownloadTask
.
Aperto MTViewController.h
e creare due prese come mostrato di seguito. Useremo la prima presa, un'istanza di UIImageView
, per visualizzare l'immagine scaricata all'utente. La seconda uscita, un'istanza di UIProgressView
, mostrerà l'avanzamento dell'attività di download.
#importare@interface MTViewController: UIViewController @property (weak, nonatomic) IBOutlet UIImageView * imageView; @property (weak, nonatomic) IBOutlet UIProgressView * progressView; @fine
Apri lo storyboard principale del progetto (Main.storyboard), trascinare a UIImageView
istanza alla vista del controller della vista e collegare la presa del controller della vista che abbiamo appena creato nel file di intestazione del controller della vista. Ripeti questo processo per la vista del progresso.
In questo esempio, non useremo il sharedSession
metodo di classe, perché abbiamo bisogno di configurare il sessione
oggetto che useremo per fare la richiesta. Aggiorna l'implementazione di viewDidLoad
come mostrato di seguito.
- (void) viewDidLoad [super viewDidLoad]; NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession * session = [NSURLSession sessionWithConfiguration: sessionConfiguration delegate: self delegateQueue: nil]; NSURLSessionDownloadTask * downloadTask = [sessione downloadTaskWithURL: [NSURL URLWithString: @ "http://cdn.tutsplus.com/mobile/uploads/2013/12/sample.jpg"]]; [download resask];
Per evitare che l'avviso del compilatore si verifichi, assicurati di conformare il file MTViewController
classe al NSURLSessionDelegate
e NSURLSessionDownloadDelegate
protocolli come mostrato di seguito.
#import "MTViewController.h" @interface MTViewController ()@fine
Nel viewDidLoad
, creiamo un'istanza di NSURLSessionConfiguration
classe invocando il defaultSessionConfiguration
metodo di classe. Come indicato nella documentazione, utilizzando la configurazione di sessione predefinita, la sessione si comporterà come un'istanza di NSURLConnection
nella sua configurazione di default, che va bene per il nostro esempio.
In questo esempio, creiamo a NSURLSession
istanza invocando il sessionWithConfiguration: delegato: delegateQueue:
metodo di classe e passare il sessionConfiguration
oggetto che abbiamo creato un momento fa. Impostiamo il controller della vista come delegato della sessione e passiamo zero
come il terzo argomento. Puoi ignorare il terzo argomento per ora. La principale differenza con l'esempio precedente è che impostiamo il sessione
delegato al controller di visualizzazione.
Per scaricare l'immagine, dobbiamo creare un'attività di download. Lo facciamo chiamando downloadTaskWithURL:
sul sessione
oggetto, passando un'istanza di NSURL
, e chiamando curriculum vitae
sull'attività di download. Avremmo potuto utilizzare un gestore di completamento come facevamo prima, ma voglio mostrarti le possibilità di usare un delegato.
Per far funzionare tutto questo, dobbiamo implementare i tre metodi delegati di NSURLSessionDownloadDelegate
protocollo, URLSession: downloadTask: didFinishDownloadingToURL:
, URLSession: downloadTask: didResumeAtOffset: expectedTotalBytes:
, e URLSession: downloadTask: downloadTask didWriteData: totalBytesWritten: totalBytesExpectedToWrite:
. L'implementazione di ciascun metodo è abbastanza semplice. È importante notare che è necessario aggiornare l'interfaccia utente sul thread principale utilizzando GCD (Grand Central Dispatch). Passando zero
come il terzo argomento di sessionWithConfiguration: delegato: delegateQueue:
, il sistema operativo ha creato una coda in background per noi. Questo va bene, ma significa anche che dobbiamo essere consapevoli del fatto che i metodi delegati vengono richiamati su un thread in background anziché sul thread principale. Costruisci il progetto ed esegui l'applicazione per vedere il risultato del nostro duro lavoro.
- (void) URLSession: (NSURLSession *) sessione downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) posizione NSData * data = [NSData dataWithContentsOfURL: posizione]; dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setHidden: YES]; [self.imageView setImage: [UIImage imageWithData: data]];); - (void) URLSession: (NSURLSession *) sessione downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes - (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesWritten totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite float progress = (double) totalBytesWritten / (double) totalBytesExpectedToWrite; dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setProgress: progress];);
Con questi due esempi, dovresti avere una conoscenza di base dei fondamenti del NSURLSession
API, come si confronta NSURLConnection
, e quali sono i suoi vantaggi. Nella parte successiva di questa serie, vedremo le funzionalità più avanzate di NSURLSession
.