Ur ett utvecklingsperspektiv är en av de viktigaste förändringarna i iOS 7 och OS X Mavericks för det saken introduktionen av NSURLSession
. Även om NSURLSession
Det kan tyckas skrämmande vid första anblicken, det är viktigt att du förstår vad det är, hur det rör sig om NSURLConnection
, och vad skillnaderna är. I denna serie tar jag dig igenom grunden för NSURLSession
så du kan utnyttja denna nya teknik i dina egna applikationer.
NSURLConnection
?Den första frågan du kanske frågar dig själv är varför Apple fann det nödvändigt att presentera NSURLSession
medan vi är helt nöjda med NSURLConnection
. Den verkliga frågan är om du är nöjd med NSURLConnection
. Kommer du ihåg den tiden du förbannade och kastade saker på NSURLConnection
? De flesta kakaoutvecklare har varit på den platsen, varför Apple bestämde sig för att gå tillbaka till ritbordet och skapa en mer elegant lösning som passar bättre för det moderna webben.
Även om NSURLSession
och NSURLConnection
har mycket gemensamt när det gäller hur de fungerar, på en grundläggande nivå är de helt annorlunda. Apple skapade NSURLSession
att likna de allmänna begreppen i NSURLConnection
, men du kommer att lära dig under denna serie att NSURLSession
är modern, lättare att använda, och byggd med mobil i åtanke.
NSURLSession
?Innan jag diskuterar skillnaderna mellan NSURLSession
och NSURLConnection
, Det är en bra idé att först titta närmare på vad NSURLSession
är. Trots sitt namn, NSURLSession
Det är inte bara en annan klass du kan använda i en iOS- eller OS X-applikation. NSURLSession
är först och främst en teknik precis som NSURLConnection
är.
NSURLSession
och NSURLConnection
båda tillhandahåller ett API för att interagera med olika protokoll, t.ex. HTTP
och HTTPS
. Sessionsobjektet, en förekomst av NSURLSession
klass, hanterar denna interaktion. Det är en mycket konfigurerbar behållare med ett elegant API som möjliggör finkorrigerad kontroll. Det erbjuder funktioner som saknas i NSURLConnection
. Vad mer med NSURLSession
, du kan utföra uppgifter som helt enkelt inte är möjliga med NSURLConnection
, som att genomföra privat surfning.
Den grundläggande arbetsenheten när du arbetar med NSURLSession
är uppgiften, en förekomst av NSURLSessionTask
. Det finns tre typer av uppgifter, data uppgifter, ladda upp uppgifter, och ladda ner uppgifter.
NSURLSessionDataTask
. Datauppgifter används för att begära data från en server, till exempel JSON-data. Den viktigaste skillnaden med uppladdning och nedladdning är att de returnerar data direkt till din ansökan istället för att gå igenom filsystemet. Data lagras endast i minnet.NSURLSessionUploadTask
är en underklass av NSURLSessionDataTask
och beter sig på ett liknande sätt. En av de viktigaste skillnaderna med en vanlig datauppgift är att uppladdningsuppgifter kan användas i en session skapad med en bakgrundssessionskonfiguration.NSURLSessionDownloadTask
, ärva direkt från NSURLSessionTask
. Den viktigaste skillnaden med datafunktioner är att en nedladdningsuppgift skriver sitt svar direkt till en temporär fil. Det här skiljer sig ganska från en vanlig datauppgift som lagrar svaret i minnet. Är det möjligt att annullera en nedladdning uppgift och återuppta det vid en senare tidpunkt.Som du kan föreställa dig är asynkronicitet ett nyckelbegrepp i NSURLSession
. De NSURLSession
API returnerar data genom att påkalla en slutförandebehandlare eller genom sessionens delegat. API av NSURLSession
designades med flexibilitet i åtanke eftersom du kommer att märka lite senare i denna handledning.
Som jag nämnde tidigare, NSURLSession
är både en teknik och en klass som du ska arbeta med. De NSURLSession
API innehåller ett antal klasser, men NSURLSession
är den viktigaste komponenten som skickar förfrågningar och mottagande av svar. Konfigurationen av sessionsobjektet hanteras emellertid av en instans av NSURLSessionConfiguration
klass. De NSURLSessionTask
klassen och dess tre konkreta underklasser är arbetarna och används alltid i samband med en session, eftersom det är den session som skapar uppgiftsobjekten.
Både NSURLSession
och NSURLConnection
lita starkt på delegationsmönstret. De NSURLSessionDelegate
protokollet förklarar en handfull delegerade metoder för att hantera händelser på sessionen. Dessutom har NSURLSessionTask
klass och underklasser vart och ett förklarar ett delegatprotokoll för hantering av händelser på uppgiftsnivå.
De NSURLSession
API bygger på klasser som du redan är bekant med, till exempel NSURL
, NSURLRequest
, och NSURLResponse
.
Hur gör det? NSURLSession
avvika från NSURLConnection
? Detta är en viktig fråga, för NSURLConnection
avlägsnas inte av Apple. Du kan fortfarande använda NSURLConnection
i dina projekt. Varför ska du använda NSURLSession
?
Det första att förstå är att NSURLSession
Exempel är det objekt som hanterar begäran och svaret. Detta liknar hur NSURLConnection
fungerar, men nyckelfaktorn är att konfigurationen av förfrågan hanteras av sessionsobjektet, vilket är ett långlivat objekt. Detta görs genom NSURLSessionConfiguration
klass. Det ger inte bara den NSURLSession
API finkorrigerad konfiguration via NSURLSessionConfiguration
klass uppmuntrar det åtskillnad av data (begäran om organ) från metadata. De NSURLSessionDownloadTask
illustrerar detta bra genom att direkt skriva svaret på filsystemet.
Autentisering är enklare och hanteras mer elegant NSURLSession
. De NSURLSession
API hanterar autentisering på en anslutningsbasis istället för på begäran, till exempel NSURLConnection
gör. De NSURLSession
API gör det också bekvämare att tillhandahålla HTTP-alternativ och varje session kan ha en separat förvaringsbehållare beroende på hur du konfigurerar sessionen.
I introduktionen berättade jag det för dig NSURLSession
ger ett modernt gränssnitt, vilket integrerar graciöst med iOS 7. Ett exempel på denna integration är NSURLSession
s out-of-process uppladdningar och nedladdningar. NSURLSession
är optimerad för att bevara batteriets livslängd, stöder paus, avbrytande och återupptagande av uppgifter samt UIKits multitasking API. Vad är inte att älska om NSURLSession
?
Ett nytt API lär sig bäst av övning så det är dags att skjuta upp Xcode och få våra fötter blöt. Starta Xcode 5, skapa ett nytt projekt genom att välja Nytt> Projekt ... från Fil menyn och välj Enkel visningsprogram mall från listan över iOS-programmallar.
Ge ditt projekt ett namn, berätta Xcode där du vill spara det och klicka Skapa. Det finns inget behov av att sätta projektet under källkontroll.
När du arbetar med NSURLSession
, Det är viktigt att förstå att sessionsobjektet, en förekomst av NSURLSession
, är stjärnspelaren. Det hanterar förfrågningarna och svaren, konfigurerar förfrågningarna, hanterar sessionens lagring och tillstånd, etc. Att skapa en session kan göras på flera sätt. Det snabbaste sättet att komma igång är att använda NSURLSession
's sharedSession
klassmetod som visas nedan.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession];
Skapa en session
objekt i visningsregulatorens viewDidLoad
metod som visas ovan. De session
objekt vi skapade är bra för vårt exempel, men du vill ha lite mer flexibilitet i de flesta fall. De session
objekt som vi just skapat använder det globala NSURLCache
, NSHTTPCookieStorage
, och NSURLCredentialStorage
. Det betyder att det fungerar ungefär som en standard implementering av NSURLConnection
.
Att sätta session
objekt att använda, låt oss fråga iTunes Store Search API och söka efter programvara som tillverkats av Apple. ITunes Store Search API är lätt att använda och kräver ingen autentisering, vilket gör den idealisk för vårt exempel.
För att fråga sök API måste vi skicka en förfrågan till https://itunes.apple.com/search
och skicka några parametrar. Som vi såg tidigare, när vi använde NSURLSession
API, en förfrågan representeras av en uppgift. För att söka sök API måste allt vi behöver är en datauppgift, en förekomst av NSURLSessionDataTask
klass. Ta en titt på den uppdaterade viewDidLoad
genomförandet visas nedan.
- (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 * svar, NSError * fel) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: dataalternativ: 0 error: nil]; NSLog (@ "% @", json); ];
Det finns ett antal metoder tillgängliga för att skapa en uppgift, men det centrala begreppet att förstå är att session
objekt gör själva uppbyggnaden och konfigurationen av uppgiften. I detta exempel åberopar vi dataTaskWithURL: completionHandler:
och skicka det till en förekomst av NSURL
såväl som en färdighetshandlare. Kompletteringshanteraren accepterar tre argument, den råa uppgifter om svaret (NSData
), den svarobjekt (NSURLResponse
), och en felobjekt (NSError
). Om begäran är framgångsrik är felobjektet noll
. Eftersom vi vet att förfrågan returnerar ett JSON-svar skapar vi en fundament objekt från data
objekt som vi har fått och loggar utmatningen till konsolen.
Det är viktigt att förstå att fel
objekt som skickas till färdigställningshanteraren är bara befolket, inte noll
, om förfrågan misslyckades eller det uppstod ett fel. Med andra ord, om förfrågan returnerade a 404
svaret lyckades förfrågan vad gäller sessionerna. De fel
objektet kommer då att vara noll
. Detta är ett viktigt begrepp att förstå när man arbetar med NSURLSession
och NSURLConnection
för den sakens skull.
Bygg projektet och kör programmet i iOS-simulatorn eller på en fysisk enhet och inspekter Xcode's Console. Ingenting skrivs ut till konsolen. Vad gick fel? Som jag nämnde tidigare, NSURLSession
API stöder pausar, avbryter och återupptar uppgifter eller förfrågningar. Detta beteende liknar det för NSOperation
och det kan påminna dig om AFNetworking-biblioteket. En uppgift har a stat
egenskap som anger om uppgiften är löpning (NSURLSessionTaskStateRunning
), suspenderad (NSURLSessionTaskStateSuspended
), avbrytande (NSURLSessionTaskStateCanceling
), eller avslutad (NSURLSessionTaskStateCompleted
). När ett sessionsobjekt skapar en uppgift startar uppgiften sitt liv i suspenderad stat. För att starta uppgiften måste vi berätta för det återuppta
genom att ringa återuppta
på uppgiften. Uppdatera viewDidLoad
metod som visas nedan, kör programmet en gång till och inspektera utmatningen i konsolen. Uppdrag slutfö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 * svar, NSError * fel) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: dataalternativ: 0 error: nil]; NSLog (@ "% @", json); ]; [dataTask resume];
I det föregående exemplet använde vi en slutföringshanterare för att behandla svaret vi mottog från förfrågan. Det är också möjligt att uppnå samma resultat genom att genomföra uppdragsdelegeringsprotokollen. Låt oss se vad som krävs för att ladda ner en bild genom att använda NSURLSession
och den NSURLSessionDownloadTask
.
Öppna MTViewController.h
och skapa två uttag som visas nedan. Vi använder det första uttaget, en förekomst av UIImageView
, för att visa den nedladdade bilden till användaren. Det andra utloppet, en förekomst av UIProgressView
, kommer att visa framstegen i hämtningsuppgiften.
#importera@interface MTViewController: UIViewController @property (svag, ickeatomisk) IBOutlet UIImageView * imageView; @property (svag, ickeatomisk) IBOutlet UIProgressView * progressView; @slutet
Öppna projektets huvudsakliga storyboard (Main.storyboard), dra a UIImageView
instämma i bildskärmens kontroll och koppla bildskärmskontrollens uttag som vi just skapat i huvudkontrollens huvudfiler. Upprepa denna process för framstegsvyn.
I det här exemplet kommer vi inte att utnyttja sharedSession
klassmetoden, eftersom vi behöver konfigurera session
objekt som vi ska använda för att göra förfrågan. Uppdatera genomförandet av viewDidLoad
enligt nedanstående.
- (void) viewDidLoad [super viewDidLoad]; NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession * session = [NSURLSession sessionWithConfiguration: sessionConfiguration delegate: self delegateQueue: nil]; NSURLSessionDownloadTask * downloadTask = [session downloadTaskWithURL: [NSURL URLWithString: @ "http://cdn.tutsplus.com/mobile/uploads/2013/12/sample.jpg"]]; [downloadTask resume];
För att förhindra att en kompilatorvarning dyker upp, se till att du överensstämmer med MTViewController
klass till NSURLSessionDelegate
och NSURLSessionDownloadDelegate
protokoll som visas nedan.
#import "MTViewController.h" @interface MTViewController ()@slutet
I viewDidLoad
, vi skapar en förekomst av NSURLSessionConfiguration
klass genom att åberopa defaultSessionConfiguration
klassmetod. Som anges i dokumentationen, uppträder sessionen med hjälp av standard sessionskonfigurationen som en förekomst av NSURLConnection
i sin standardkonfiguration, vilket är bra för vårt exempel.
I det här exemplet skapar vi en NSURLSession
exempel genom att åberopa sessionWithConfiguration: delegat: delegateQueue:
klassmetod och passera sessionConfiguration
objekt vi skapade för en stund sedan. Vi ställde upp kontrollen som session delegat och passerar noll
som det tredje argumentet. Du kan ignorera det tredje argumentet för nu. Huvudskillnaden med föregående exempel är att vi ställer in session
s delegerad till vaktkontrollen.
För att ladda ner bilden måste vi skapa en nedladdningsuppgift. Vi gör detta genom att ringa downloadTaskWithURL:
på session
objekt, passerar en instans av NSURL
, och ringer återuppta
på hämtningsuppgiften. Vi kunde ha använt en färdighetshandlare som vi gjorde tidigare, men jag vill visa dig möjligheterna att använda en delegat istället.
För att göra allt detta måste vi genomföra de tre delegerade metoderna i NSURLSessionDownloadDelegate
protokoll, URLSession: downloadTask: didFinishDownloadingToURL:
, URLSession: downloadTask: didResumeAtOffset: expectedTotalBytes:
, och URLSession: downloadTask: downloadTask didWriteData: totalBytesWritten: totalBytesExpectedToWrite:
. Genomförandet av varje metod är ganska enkelt. Det är viktigt att notera att vi behöver uppdatera användargränssnittet på huvudtråden med hjälp av GCD (Grand Central Dispatch). Genom att passera noll
som tredje argumentet av sessionWithConfiguration: delegat: delegateQueue:
, operativsystemet skapade en bakgrundskö för oss. Det här är bra, men det betyder också att vi måste vara medvetna om att delegatsmetoderna är åberopade på en bakgrundstråd istället för huvudtråden. Bygg projektet och kör programmet för att se resultatet av vårt hårda arbete.
- (void) URLSession: (NSURLSession *) session nedladdningTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) plats NSData * data = [NSData dataWithContentsOfURL: location]; dispatch_async (dispatch_get_main_queue (), ^ self.progressView setHidden: YES]; [self.imageView setImage: [UIImage imageWithData: data]];); - (void) URLSession: (NSURLSession *) session nedladdningTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes - (void) URLSession: (NSURLSession *) session nedladdningTask: (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];);
Med dessa två exempel borde du ha en grundläggande förståelse för grunden för NSURLSession
API, hur det jämförs med NSURLConnection
, och vad dess fördelar är. I nästa del av denna serie tittar vi på mer avancerade funktioner i NSURLSession
.