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.
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.
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.
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.
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.
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.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.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.
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.
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.
NSURLSession
API se bazează pe clasele pe care deja le cunoașteți, cum ar fi NSURL
, NSURLRequest
, și NSURLResponse
.
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 NSURLSession
descă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
?
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ă.
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
.
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];
Î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
.
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.
Î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 sesiune
delegat 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.
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];);
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
.