Lucrul în rețea cu NSURLSession Partea 1

Din perspectiva unui dezvoltator, una dintre cele mai semnificative modificări în iOS 7 și OS X Mavericks pentru acest lucru este introducerea NSURLSession. Chiar dacă NSURLSession poate părea descurajant la prima vedere, este important să înțelegeți ce este, cum se leagă NSURLConnection, și care sunt diferențele. În această serie, vă voi trece prin fundamentele NSURLSession astfel încât să puteți profita de această nouă tehnologie în propriile aplicații.


De ce să înlocuiți NSURLConnection?

Prima întrebare pe care o puteți întreba este motivul pentru care Apple a considerat necesar să introducă NSURLSession în timp ce suntem cu adevărat mulțumiți NSURLConnection. Întrebarea adevărată este dacă tu sunteți fericit cu NSURLConnection. Îți amintești de timpul când blesteam și arunci lucrurile NSURLConnection? Cei mai mulți dezvoltatori de cacao au fost în acel loc, motiv pentru care Apple a decis să se întoarcă la desen și să creeze o soluție mai elegantă, mai potrivită pentru web-ul modern.

Chiar dacă NSURLSession și NSURLConnection au multe în comun în ceea ce privește modul în care funcționează, la un nivel fundamental, sunt destul de diferite. Apple a creat NSURLSession să semene cu conceptele generale ale NSURLConnection, dar veți învăța în cursul acestei serii că NSURLSession este modern, mai ușor de utilizat și construit cu mobilitate în minte.


Ce este NSURLSession?

Înainte de a discuta diferențele dintre NSURLSession și NSURLConnection, este o idee bună să priviți mai întâi la ce NSURLSession este. În ciuda numelui său, NSURLSession nu este doar o altă clasă pe care o puteți folosi într-o aplicație iOS sau OS X. NSURLSession este în primul rând o tehnologie la fel ca NSURLConnection este.

Sesiunile sunt Containere

NSURLSession și NSURLConnection ambele furnizează un API pentru interacțiunea cu diferite protocoale, cum ar fi HTTP și HTTPS. Obiectul sesiune, o instanță a NSURLSession clasa, este ceea ce gestionează această interacțiune. Este un container foarte configurabil, cu un API elegant, care permite controlul cu granulație fină. Acesta oferă caracteristici care sunt absente în NSURLConnection. Mai mult, cu NSURLSession, puteți realiza sarcini care nu sunt pur și simplu posibile cu NSURLConnection, cum ar fi implementarea navigării private.

Sarcini

Unitatea de bază în care lucrați NSURLSession este sarcina, un exemplu de NSURLSessionTask. Există trei tipuri de sarcini, sarcinile de date, încărcați sarcinile, și descărcați sarcini.

  • Veți folosi cel mai adesea sarcini de date, care sunt cazuri de NSURLSessionDataTask. Sarcinile de date sunt utilizate pentru a solicita date de la un server, cum ar fi datele JSON. Principala diferență cu sarcinile de încărcare și descărcare este aceea că acestea returnează datele direct aplicației în loc să treacă prin sistemul de fișiere. Datele sunt stocate numai în memorie.
  • După cum sugerează și numele, sarcinile de încărcare sunt utilizate pentru a încărca datele către o destinație la distanță. NSURLSessionUploadTask este o subclasă de NSURLSessionDataTask și se comportă într-un mod similar. Una dintre diferențele cheie cu o sarcină obișnuită de date este că sarcinile de încărcare pot fi utilizate într-o sesiune creată cu o configurație de sesiune de fundal.
  • Descărcați sarcini, instanțe NSURLSessionDownloadTask, moșteni direct de la NSURLSessionTask. Cea mai importantă diferență cu sarcinile de date este că o sarcină de descărcare scrie răspunsul său direct la un fișier temporar. Acest lucru este destul de diferit de o sarcină obișnuită de date care stochează răspunsul în memorie. Este posibil să Anulare o sarcină de descărcare și relua la un moment dat.

După cum vă puteți imagina, asincronitatea este un concept cheie în NSURLSession. NSURLSession API returnează date prin invocarea unui handler de completare sau prin intermediul delegatului sesiunii. API-ul din NSURLSession a fost proiectat cu flexibilitate în minte, după cum veți observa un pic mai târziu în acest tutorial.

Faceți cunoștință cu familia

După cum am menționat mai devreme, NSURLSession este atât o tehnologie cât și o clasă cu care veți lucra. NSURLSession API găzduiește o serie de clase, dar NSURLSession este componenta cheie care trimite cereri și primește răspunsuri. Configurația obiectului sesiunii, cu toate acestea, este tratată de o instanță a NSURLSessionConfiguration clasă. NSURLSessionTask clasa și cele trei subclase concrete sunt lucrătorii și sunt folosiți întotdeauna împreună cu o sesiune, deoarece este sesiunea care creează obiectele de activitate.

Delegație

Ambii NSURLSession și NSURLConnection se bazează foarte mult pe modelul delegării. NSURLSessionDelegate protocol declară o mână de metode delegate pentru gestionarea evenimentelor la nivel de sesiune. In plus NSURLSessionTask clasa și subclasele fiecare declară un protocol delegat pentru a gestiona evenimente la nivel de activitate.

Prieteni vechi

NSURLSession API se bazează pe clasele pe care deja le cunoașteți, cum ar fi NSURL, NSURLRequest, și NSURLResponse.


Care sunt diferențele??

Cum se NSURLSession diferă de NSURLConnection? Aceasta este o întrebare importantă, pentru că NSURLConnection nu este depreciat de Apple. Puteți utiliza în continuare NSURLConnection în proiectele dvs. De ce ar trebui să utilizați NSURLSession?

Primul lucru de înțeles este că NSURLSession instanta este obiectul care gestioneaza cererea si raspunsul. Acest lucru este similar cu modul în care NSURLConnection funcționează, dar diferența cheie este că configurația cererii este tratată de obiectul sesiune, care este un obiect de lungă durată. Acest lucru se face prin NSURLSessionConfiguration clasă. Nu numai că furnizează NSURLSession API configurație cu granulație fină prin NSURLSessionConfiguration , încurajează separarea datelor (corpul solicitării) de metadate. NSURLSessionDownloadTask ilustrează acest lucru prin scrierea directă a răspunsului la sistemul de fișiere.

Autentificarea este mai ușoară și manipulată mai elegant de către NSURLSession. NSURLSession API se ocupă de autentificare pe bază de conexiune în loc de cerere, cum ar fi NSURLConnection face. NSURLSession De asemenea, API face mai convenabil să furnizeze opțiuni HTTP și fiecare sesiune poate avea un container de stocare separat, în funcție de modul în care configurați sesiunea.

În introducere, ți-am spus asta NSURLSession oferă o interfață modernă, care se integrează grațios cu iOS 7. Un exemplu de integrare este NSURLSessiondescărcări și descărcări în afara procesului. NSURLSession este optimizat pentru a menține durata de viață a bateriei, suportă întreruperea, anularea și reluarea activităților, precum și API-ul multitasking UIKit. Ce nu trebuie sa iubesti NSURLSession?


Noțiuni de bază picioarele voastre umede

Pasul 1: Configurarea proiectului

Un nou API este cel mai bine invatat de practica, asa ca este timpul sa incarci Xcode si sa ne umezi picioarele. Lansați Xcode 5, creați un nou proiect selectând Nou> Proiect ... de la Fişier meniu și selectați Vizualizare individuală șablon din lista de șabloane de aplicații iOS.


Dă-ți un nume unui proiect, spune-i lui Xcode unde vrei să îl salvezi și lovi-l Crea. Nu este nevoie să puneți proiectul sub control sursă.


Pasul 2: Creați un obiect de sesiune

Când lucrați cu NSURLSession, este important să înțelegem că obiectul sesiune, o instanță de NSURLSession, este jucătorul de stele. Acesta gestionează cererile și răspunsurile, configurează solicitările, gestionează stocarea sesiunii și starea etc. Crearea unei sesiuni se poate face în mai multe moduri. Cel mai rapid mod de a începe este acela de a utiliza NSURLSession„s sharedSession clasă, după cum se arată mai jos.

 - (vid) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; 

Creeaza o sesiune obiect în controlerul de vizualizare viewDidLoad așa cum se arată mai sus. sesiune obiectul pe care l-am creat este bine pentru exemplul nostru, dar probabil că doriți mai multă flexibilitate în majoritatea cazurilor. sesiune obiectul pe care tocmai l-am creat îl folosește pe glob NSURLCache, NSHTTPCookieStorage, și NSURLCredentialStorage. Aceasta înseamnă că funcționează destul de similar cu o implementare implicită a NSURLConnection.

Pasul 3: Creați o sarcină de date

Pentru a pune sesiune obiect de utilizare, să interogăm API-ul de căutare iTunes Store și să căutăm software făcut de Apple. API-ul de căutare iTunes Store Search este ușor de utilizat și nu necesită autentificare, ceea ce îl face ideal pentru exemplul nostru.

Pentru a interoga API-ul de căutare, trebuie să trimitem o solicitare https://itunes.apple.com/search și să treacă câțiva parametri. După cum am văzut mai devreme, când folosim NSURLSession API, o cerere este reprezentată de o sarcină. Pentru a interoga API-ul de căutare, tot ce ne trebuie este o sarcină de date, o instanță a NSURLSessionDataTask clasă. Uitați-vă la actualizată viewDidLoad implementarea de mai jos.

 - (vid) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [data sesiuneTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completareHandler: ^ (NSData * date, NSURLResponse * răspuns, eroare NSError * NSDictionary * json = [NSJSONSerializare JSONObjectWithData: opțiuni de date: 0 eroare: zero]; NSLog (@ "% @", json); ]; 

Există o serie de metode disponibile pentru a crea o sarcină, dar conceptul cheie de înțeles este că sesiune Obiect face crearea și configurarea reală a sarcinii. În acest exemplu, invocăm dataTaskWithURL: completionHandler: și să-i dați un exemplu NSURL precum și un handler de completare. Operatorul de terminare acceptă trei argumente: date brute ale răspunsului (NSData), răspunsul obiect (NSURLResponse), si un obiect de eroare (NSError). Dacă cererea are succes, obiectul de eroare este zero. Deoarece știm că cererea returnează un răspuns JSON, noi creăm a fundație obiect de la date obiect pe care l-am primit și conectați ieșirea la consola.

Este important să înțelegeți că eroare obiect trecut la manipulatorul de finalizare este doar populate, nu zero, dacă cererea a eșuat sau a apărut o eroare. Cu alte cuvinte, dacă cererea a returnat a 404 răspunsul, cererea a reușit în ceea ce privește sesiunile. eroare obiect va fi atunci zero. Acesta este un concept important pentru a înțelege atunci când lucrați cu NSURLSession și NSURLConnection pentru asta.

Construiți proiectul și rulați aplicația în Simulatorul iOS sau pe un dispozitiv fizic și inspectați Consola Xcode. Nimic nu este imprimat pe consola. Ce a mers prost? Așa cum am menționat mai devreme, NSURLSession API acceptă întreruperea, anularea și reluarea sarcinilor sau solicitărilor. Acest comportament este similar cu cel al lui NSOperation și vă poate aminti de biblioteca AFNetworking. O sarcină are a stat care indică dacă este sarcina alergare (NSURLSessionTaskStateRunning), suspendat (NSURLSessionTaskStateSuspended), anulare (NSURLSessionTaskStateCanceling), sau terminat (NSURLSessionTaskStateCompleted). Când un obiect de sesiune creează o sarcină, sarcina își începe viața în suspendat stat. Pentru a începe sarcina, trebuie să o spunem relua sunând relua cu privire la sarcină. Actualizați viewDidLoad după cum se arată mai jos, executați încă o dată aplicația și examinați ieșirea din consola. Misiune indeplinita.

 - (vid) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [data sesiuneTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completareHandler: ^ (NSData * date, NSURLResponse * răspuns, eroare NSError * NSDictionary * json = [NSJSONSerializare JSONObjectWithData: opțiuni de date: 0 eroare: zero]; NSLog (@ "% @", json); ]; [dataTask resume]; 

Descărcarea unei resurse la distanță

În exemplul anterior, am utilizat un handler de completare pentru a procesa răspunsul pe care l-am primit din solicitare. De asemenea, este posibil să se obțină același rezultat prin implementarea protocoalelor delegate de sarcini. Să vedem ce este nevoie pentru a descărca o imagine prin folosirea fondurilor NSURLSession si NSURLSessionDownloadTask.

Pasul 1: Creați interfața de utilizator

Deschis MTViewController.h și creați două ieșiri după cum se arată mai jos. Vom folosi prima priză, o instanță de UIImageView, pentru a afișa imaginea descărcată către utilizator. A doua ieșire, un exemplu de UIProgressView, va arăta progresul sarcinii de descărcare.

 #import  @ interfață MTViewController: UIViewController @property (slab, nonatomic) IBOutlet UIImageView * imageView; @property (slab, nonatomic) IBOutlet UIProgressView * progressView; @Sfârșit

Deschideți tabloul de bord principal al proiectului (Main.storyboard), trageți a UIImageView la vizualizarea controlerului de vizualizare și conectați priza de controler de vizualizare pe care tocmai am creat-o în fișierul antet al controlerului de vizualizare. Repetați acest proces pentru vizualizarea progresului.


Pasul 2: Creați o sarcină de descărcare

În acest exemplu, nu vom folosi sharedSession metoda de clasă, deoarece trebuie să configuram sesiune obiect pe care îl vom folosi pentru a face cererea. Actualizați punerea în aplicare a viewDidLoad așa cum se arată mai jos.

 - (vid) viewDidLoad [super viewDidLoad]; NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession * session = [sesiunea NSURLSessionWithConfiguration: delegația sesiuniiConfiguration: self delegateQueue: nil]; NSURLSessionDownloadTask * downloadTask = [sesiunea downloadTaskWithURL: [NSURL URLWithString: @ "http://cdn.tutsplus.com/mobile/uploads/2013/12/sample.jpg"]]; [reluarea descărcăriiTask]; 

Pentru a împiedica apariția oricărui avertisment de la compilator, asigurați-vă că respectați MTViewController clasa la NSURLSessionDelegate și NSURLSessionDownloadDelegate protocoale, după cum se arată mai jos.

 #import "MTViewController.h" @interface MTViewController ()  @Sfârșit

În viewDidLoad, vom crea o instanță a NSURLSessionConfiguration clasa invocând defaultSessionConfiguration clasă. După cum se precizează în documentație, prin utilizarea configurației implicite a sesiunii, sesiunea se va comporta mult ca o instanță de NSURLConnection în configurația sa implicită, ceea ce este bine pentru exemplul nostru.

În acest exemplu, creăm a NSURLSession instanță invocând sessionWithConfiguration: delegat: delegateQueue: clasă și să treacă sessionConfiguration obiect pe care l-am creat acum un moment. Am setat controlerul de vizualizare ca delegat al sesiunii și treci zero ca al treilea argument. Puteți ignora cel de-al treilea argument pentru moment. Principala diferență față de exemplul anterior este aceea că am setat sesiunedelegat la controlorul de vizualizare.

Pentru a descărca imaginea, trebuie să creați o sarcină de descărcare. Facem asta prin chemare downloadTaskWithURL: pe sesiune obiect, trecând o instanță de NSURL, și chemarea relua despre sarcina de descărcare. Am fi putut folosi un handler de finalizare cum am făcut-o mai devreme, dar vreau să vă arăt posibilitățile de a utiliza un delegat în schimb.

Pasul 3: Implementarea Protocolului delegat

Pentru a face toate aceste lucruri, trebuie să punem în aplicare cele trei metode delegate ale NSURLSessionDownloadDelegate protocol, URLSession: downloadTask: didFinishDownloadingToURL:, URLSession: downloadTask: didResumeAtOffset: expectedTotalBytes:, și URLSession: downloadTask: downloadTask didWriteData: totalBytesWritten: totalBytesExpectedToWrite:. Implementarea fiecărei metode este destul de ușoară. Este important să rețineți că trebuie să actualizăm interfața de utilizator pe firul principal folosind GCD (Grand Central Dispatch). Trecând zero ca al treilea argument al sessionWithConfiguration: delegat: delegateQueue:, sistemul de operare a creat o coadă de fundal pentru noi. Acest lucru este bine, dar înseamnă, de asemenea, că trebuie să fim conștienți de faptul că metodele delegate sunt invocate pe un fir de fund în loc de firul principal. Construiți proiectul și rulați aplicația pentru a vedea rezultatul muncii noastre grele.

 - (void) URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) locație NSData * data = [NSData dataWithContentsOfURL: locație]; dispatch_async (dispatch_get_main_queue (), ^ [auto.progressView setHidden: YES]; [auto.imageView setImage: [UIImage imageWithData: data]];));  - (void) Adresă URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesWritten totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite float progress = (dublu) totalBytesWritten / (dublu) totalBytesExpectedToWrite; dispatch_async (dispatch_get_main_queue (), ^ [auto.progressView setProgress: progress];); 

Concluzie

Cu aceste două exemple, trebuie să aveți o înțelegere de bază a fundamentelor NSURLSession API, cum se compară cu acesta NSURLConnection, și care sunt avantajele sale. În următoarea parte a acestei serii, vom analiza caracteristicile mai avansate din NSURLSession.

Cod