Fra en utviklerperspektiv er en av de mest signifikante endringene i iOS 7 og OS X Mavericks for det saks skyld introduksjonen av NSURLSession
. Selv om NSURLSession
kan virke skremmende ved første øyekast, det er viktig at du forstår hva det er, hvordan det gjelder NSURLConnection
, og hva forskjellene er. I denne serien tar jeg deg gjennom grunnleggende NSURLSession
slik at du kan dra nytte av denne nye teknologien i dine egne applikasjoner.
NSURLConnection
?Det første spørsmålet du kan spørre deg selv er hvorfor Apple fant det nødvendig å introdusere NSURLSession
mens vi er helt fornøyd med NSURLConnection
. Det virkelige spørsmålet er om du er trives med NSURLConnection
. Husker du den tiden du forbannet og kastet ting på NSURLConnection
? De fleste kakaoutviklere har vært på det stedet, og derfor bestemte Apple seg for å gå tilbake til tegnebrettet og skape en mer elegant løsning, bedre egnet for den moderne web.
Selv om NSURLSession
og NSURLConnection
har mye til felles når det gjelder hvordan de jobber, på et grunnleggende nivå, er de ganske forskjellige. Apple opprettet NSURLSession
å ligne de generelle konseptene til NSURLConnection
, men du vil lære i løpet av denne serien at NSURLSession
er moderne, enklere å bruke, og bygget med mobil i tankene.
NSURLSession
?Før jeg diskuterer forskjellene mellom NSURLSession
og NSURLConnection
, det er en god ide å først se nærmere på hva NSURLSession
er. Til tross for navnet sitt, NSURLSession
er ikke bare en annen klasse du kan bruke i en iOS- eller OS X-applikasjon. NSURLSession
er først og fremst en teknologi akkurat som NSURLConnection
er.
NSURLSession
og NSURLConnection
Begge gir en API for å samhandle med ulike protokoller, for eksempel HTTP
og HTTPS
. Sessionsobjektet, en forekomst av NSURLSession
klassen, er det som forvalter denne interaksjonen. Det er en svært konfigurerbar beholder med en elegant API som gir mulighet for finkornet kontroll. Det tilbyr funksjoner som er fraværende i NSURLConnection
. Hva mer med NSURLSession
, Du kan utføre oppgaver som ikke er mulig med NSURLConnection
, for eksempel implementering av privat surfing.
Den grunnleggende arbeidsenheten når du arbeider med NSURLSession
er oppgaven, en forekomst av NSURLSessionTask
. Det er tre typer oppgaver, dataoppgaver, laste opp oppgaver, og nedlastingsoppgaver.
NSURLSessionDataTask
. Dataoppgaver brukes til å be om data fra en server, for eksempel JSON-data. Hovedforskjellen med opplastings- og nedlastingsoppgaver er at de returnerer data direkte til søknaden din i stedet for å gå gjennom filsystemet. Dataene lagres bare i minnet.NSURLSessionUploadTask
er en underklasse av NSURLSessionDataTask
og oppfører seg på lignende måte. En av de viktigste forskjellene med en vanlig dataoppgave er at opplastingsoppgaver kan brukes i en økt som er opprettet med en bakgrunnssesjonskonfigurasjon.NSURLSessionDownloadTask
, arve direkte fra NSURLSessionTask
. Den viktigste forskjellen med dataoppgaver er at en nedlastingsoppgave skriver sitt svar direkte til en midlertidig fil. Dette er ganske forskjellig fra en vanlig dataoppgave som lagrer svaret i minnet. Det er mulig å Avbryt en nedlastingsoppgave og gjenoppta det på et senere tidspunkt.Som du kan forestille deg, er asynkronicitet et nøkkelbegrep i NSURLSession
. De NSURLSession
API returnerer data ved å påkalle en sluttbehandler eller gjennom øktens delegat. API av NSURLSession
ble designet med fleksibilitet i tankene som du vil legge merke til litt senere i denne opplæringen.
Som jeg nevnte tidligere, NSURLSession
er både en teknologi og en klasse som du skal jobbe med. De NSURLSession
API huser en rekke klasser, men NSURLSession
er nøkkelkomponenten som sender forespørsler og mottar svar. Konfigurasjonen av sesjonsobjektet håndteres imidlertid av en forekomst av NSURLSessionConfiguration
klasse. De NSURLSessionTask
klassen og de tre konkrete underklassene er arbeiderne og brukes alltid i forbindelse med en økt som det er økten som lager oppgavene.
Både NSURLSession
og NSURLConnection
stole tungt på delegasjonsmønsteret. De NSURLSessionDelegate
protokollen erklærer en håndfull delegerte metoder for å håndtere hendelser på øktnivå. i tillegg NSURLSessionTask
Klasser og underklasser hver erklære en delegatprotokoll for å håndtere hendelsesnivåhendelser.
De NSURLSession
API bygger på klasser som du allerede er kjent med, for eksempel NSURL
, NSURLRequest
, og NSURLResponse
.
Hvordan gjør NSURLSession
Er forskjellig fra NSURLConnection
? Dette er et viktig spørsmål, fordi NSURLConnection
blir ikke avskrevet av Apple. Du kan fortsatt bruke NSURLConnection
i dine prosjekter. Hvorfor skal du bruke NSURLSession
?
Det første å forstå er at NSURLSession
eksempel er objektet som styrer forespørselen og svaret. Dette ligner på hvordan NSURLConnection
fungerer, men hovedforskjellen er at konfigurasjonen av forespørselen håndteres av øktobjektet, som er et langt levet objekt. Dette gjøres gjennom NSURLSessionConfiguration
klasse. Ikke bare gir den NSURLSession
API finkornet konfigurasjon gjennom NSURLSessionConfiguration
klassen, oppfordrer den adskillelsen av data (forespørsel) fra metadata. De NSURLSessionDownloadTask
illustrerer dette bra ved å skrive svaret på filsystemet direkte.
Autentisering er enklere og håndteres mer elegant NSURLSession
. De NSURLSession
API håndterer autentisering på en tilkoblingsbasis i stedet for på forespørsel, som NSURLConnection
gjør. De NSURLSession
API gjør det også lettere å gi HTTP-alternativer, og hver økt kan ha en separat lagringsbeholder avhengig av hvordan du konfigurerer økten.
I introduksjonen fortalte jeg deg det NSURLSession
gir et moderne grensesnitt, som integrerer grasiøst med iOS 7. Et eksempel på denne integrasjonen er NSURLSession
's out-of-process opplastinger og nedlastinger. NSURLSession
er optimalisert for å bevare batteriets levetid, støtter pauser, kansellering og gjenopptak av oppgaver, samt UIKits multitasking API. Hva er ikke å elske om NSURLSession
?
En ny API er best lært av praksis, så det er på tide å brann opp Xcode og få føttene våte. Start Xcode 5, opprett et nytt prosjekt ved å velge Nytt> Prosjekt ... fra Fil menyen, og velg Enkeltvisningsprogram mal fra listen over iOS-applikasjonsmaler.
Gi prosjektet ditt et navn, fortell Xcode hvor du vil lagre det, og klikk Skape. Det er ikke nødvendig å sette prosjektet under kildekontroll.
Når du arbeider med NSURLSession
, Det er viktig å forstå at øktobjektet, en forekomst av NSURLSession
, er stjernespilleren. Den håndterer forespørsler og svar, konfigurerer forespørsler, styrer lagringsplass og stat, etc. Opprettelse av en økt kan gjøres på flere måter. Den raskeste måten å komme i gang er å bruke NSURLSession
's sharedSession
klassemetode som vist nedenfor.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession];
Lage en økt
objekt i visningsregulatorens viewDidLoad
metode som vist ovenfor. De økt
objekt vi opprettet er bra for vårt eksempel, men du vil sikkert ha litt mer fleksibilitet i de fleste tilfeller. De økt
objekt vi nettopp har laget, bruker den globale NSURLCache
, NSHTTPCookieStorage
, og NSURLCredentialStorage
. Dette betyr at det fungerer ganske lik en standard implementering av NSURLConnection
.
Å sette økt
protestere mot bruk, la oss spørre iTunes Store Search API og søke etter programvare laget av Apple. ITunes Store Search API er lett å bruke og krever ingen godkjenning, noe som gjør den ideell for eksempelet vårt.
For å spørre søkeprogrammet, må vi sende en forespørsel til https://itunes.apple.com/search
og pass noen parametere. Som vi så tidligere, da vi brukte NSURLSession
API, en forespørsel representeres av en oppgave. For å spørre søkeprogrammet, er alt vi trenger en datahandel, en forekomst av NSURLSessionDataTask
klasse. Ta en titt på den oppdaterte viewDidLoad
implementering vist nedenfor.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (NSData * data, NSURLResponse * respons, NSError * feil) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: dataalternativer: 0 feil: null]; NSLog (@ "% @", json); ];
Det finnes en rekke metoder tilgjengelig for å opprette en oppgave, men nøkkelbegrepet å forstå er at økt
objekt gjør selve opprettelsen og konfigurasjonen av oppgaven. I dette eksemplet påberoper vi oss dataTaskWithURL: completionHandler:
og gi det en forekomst av NSURL
samt en ferdigstillingshåndterer. Fullføringsbehandleren aksepterer tre argumenter, den Rå data av svaret (NSData
), den responsobjekt (NSURLResponse
), og en feilobjekt (NSError
). Hvis forespørselen er vellykket, er feilobjektet nil
. Fordi vi vet at forespørselen returnerer et JSON-svar, oppretter vi en Fundament objekt fra data
objekt som vi har mottatt og logg utgangen til konsollen.
Det er viktig å forstå at feil
objektet som sendes til fullføringsbehandleren, er bare befolket, ikke nil
, hvis forespørselen mislyktes eller det oppsto en feil. Med andre ord, hvis forespørselen returnerte a 404
svaret, ble forespørselen lykkes så langt som øktene angår. De feil
objektet vil da være nil
. Dette er et viktig konsept å forstå når du arbeider med NSURLSession
og NSURLConnection
for den saks skyld.
Bygg prosjektet og kjør programmet i iOS-simulatoren eller på en fysisk enhet, og inspiser Xcode's Console. Ingenting skrives ut på konsollen. Hva gikk galt? Som jeg tidligere nevnte, NSURLSession
API støtter pauser, kansellering og gjenopptakelse av oppgaver eller forespørsler. Denne oppførselen ligner på NSOperation
og det kan minne deg om AFNetworking-biblioteket. En oppgave har a stat
Egenskap som angir om oppgaven er løping (NSURLSessionTaskStateRunning
), suspendert (NSURLSessionTaskStateSuspended
), avbryter (NSURLSessionTaskStateCanceling
), eller fullført (NSURLSessionTaskStateCompleted
). Når et øktobjekt oppretter en oppgave, starter oppgaven sitt liv i suspendert stat. For å starte oppgaven må vi fortelle det til gjenoppta
ved å ringe gjenoppta
på oppgaven. Oppdater viewDidLoad
metode som vist nedenfor, kjør programmet en gang til, og inspiser utgangen i konsollen. Oppdrag utført.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (NSData * data, NSURLResponse * respons, NSError * feil) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: dataalternativer: 0 feil: null]; NSLog (@ "% @", json); ]; [dataTask CV];
I det forrige eksempelet benyttet vi en fullføringshåndterer til å behandle svaret vi mottok fra forespørselen. Det er også mulig å oppnå det samme resultatet ved å implementere oppgavegruppeprotokollen (e). La oss se hva som kreves for å laste ned et bilde ved å utnytte NSURLSession
og NSURLSessionDownloadTask
.
Åpen MTViewController.h
og opprett to utsalgssteder som vist nedenfor. Vi bruker det første utløpet, en forekomst av UIImageView
, for å vise det nedlastede bildet til brukeren. Det andre utløpet, en forekomst av UIProgressView
, vil vise fremdriften av nedlastingsoppgaven.
#importere@interface MTViewController: UIViewController @property (svak, ikkeatomisk) IBOutlet UIImageView * imageView; @property (svak, ikkeatomisk) IBOutlet UIProgressView * progressView; @slutt
Åpne prosjektets hovedhistorieplate (Main.storyboard), dra a UIImageView
forekommer til visningskontrollørens visning, og koble utsignalkontrollens uttak som vi nettopp har opprettet i tittelkontrollens headerfil. Gjenta denne prosessen for fremdriftsvisningen.
I dette eksemplet vil vi ikke gjøre bruk av sharedSession
klassemetode, fordi vi må konfigurere økt
objekt som vi vil bruke til å gjøre forespørselen. Oppdater implementeringen av viewDidLoad
som vist under.
- (void) viewDidLoad [super viewDidLoad]; NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession * session = [NSURLSession sessionWithConfiguration: sessionConfiguration delegate: self delegateQueue: null]; NSURLSessionDownloadTask * downloadTask = [Session downloadTaskWithURL: [NSURL URLWithString: @ "http://cdn.tutsplus.com/mobile/uploads/2013/12/sample.jpg"]]; [downloadTask resume];
For å forhindre at en kompilervarsel kommer opp, må du sørge for at den samsvarer med MTViewController
klasse til NSURLSessionDelegate
og NSURLSessionDownloadDelegate
protokoller som vist nedenfor.
#import "MTViewController.h" @interface MTViewController ()@slutt
I viewDidLoad
, vi lager en forekomst av NSURLSessionConfiguration
klasse ved å påkalle defaultSessionConfiguration
klassemetode. Som nevnt i dokumentasjonen, oppfører sesjonen seg mye som en forekomst av NSURLConnection
i standardkonfigurasjonen, som er bra for vårt eksempel.
I dette eksempelet oppretter vi en NSURLSession
eksempel ved å påkalle sessionWithConfiguration: delegat: delegateQueue:
klassemetode og passere sessionConfiguration
objekt vi opprettet for et øyeblikk siden. Vi stiller visningscontrolleren som øktdelegate og passerer nil
som det tredje argumentet. Du kan ignorere det tredje argumentet for nå. Hovedforskjellen med det forrige eksempelet er at vi setter økt
s delegert til visningskontrolløren.
For å laste ned bildet må vi opprette en nedlastingsoppgave. Vi gjør dette ved å ringe downloadTaskWithURL:
på økt
objekt, passerer en forekomst av NSURL
, og ringer gjenoppta
på nedlastingsoppgaven. Vi kunne ha brukt en ferdigstillingshåndterer som vi gjorde tidligere, men jeg vil vise deg mulighetene til å bruke en delegat i stedet.
For å gjøre alt dette arbeidet, må vi implementere de tre delegerte metodene til NSURLSessionDownloadDelegate
protokollen, URLSession: downloadTask: didFinishDownloadingToURL:
, URLSession: downloadTask: didResumeAtOffset: expectedTotalBytes:
, og URLSession: downloadTask: downloadTask didWriteData: totalBytesWritten: totalBytesExpectedToWrite:
. Gjennomføringen av hver metode er ganske enkelt. Det er viktig å merke seg at vi må oppdatere brukergrensesnittet på hovedtråden ved hjelp av GCD (Grand Central Dispatch). Ved å passere nil
som det tredje argumentet til sessionWithConfiguration: delegat: delegateQueue:
, operativsystemet opprettet en bakgrunnskø for oss. Dette er greit, men det betyr også at vi må være oppmerksomme på at delegatemetoder påberopes på en bakgrunnstråd i stedet for hovedtråden. Bygg prosjektet og kjør programmet for å se resultatet av vårt harde arbeid.
- (void) URLSession: (NSURLSession *) sessionsnedlastningTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) sted NSData * data = [NSData dataWithContentsOfURL: location]; dispatch_async (dispatch_get_main_queue (), ^ self.progressView setHidden: YES]; [self.imageView setImage: [UIImage imageWithData: data]];); - (ugyldig) URLSession: (NSURLSession *) sessionsnedlastningTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset forventetTotalBytes: (int64_t) forventetTotalBytes - (ugyldig) URLSession: (NSURLSession *) økt nedlastingTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) bytesVerdet totaltBytesWritten: (int64_t) totalBytesBrevet totaltBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite float progress = (double) totalBytesWritten / (double) totalBytesExpectedToWrite; dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setProgress: progress];);
Med disse to eksemplene bør du ha en grunnleggende forståelse av grunnleggende for NSURLSession
API, hvordan det sammenlignes med NSURLConnection
, og hva fordelene er det. I neste del av denne serien vil vi se på mer avanserte funksjoner av NSURLSession
.