Vanuit het perspectief van een ontwikkelaar is een van de belangrijkste wijzigingen in iOS 7, en OS X Mavericks, de introductie van NSURLSession
. Hoewel NSURLSession
lijkt op het eerste gezicht misschien ontmoedigend, het is belangrijk dat je begrijpt wat het is, hoe het zich verhoudt tot wat het is NSURLConnection
, en wat de verschillen zijn. In deze serie zal ik je door de grondbeginselen van NSURLSession
zodat u kunt profiteren van deze nieuwe technologie in uw eigen toepassingen.
NSURLConnection
?De eerste vraag die je jezelf misschien zou stellen is waarom Apple het nodig vond om te introduceren NSURLSession
terwijl we perfect gelukkig zijn met NSURLConnection
. De echte vraag is of jij zijn blij met NSURLConnection
. Herinner je je die keer dat je vloekte en dingen aan het gooien was? NSURLConnection
? De meeste Cocoa-ontwikkelaars waren op die plaats. Daarom besloot Apple terug te gaan naar de tekentafel en een elegantere oplossing te creëren, beter geschikt voor het moderne web..
Hoewel NSURLSession
en NSURLConnection
hebben veel gemeen in termen van hoe ze werken, op een fundamenteel niveau, ze zijn heel anders. Apple heeft gemaakt NSURLSession
om op de algemene concepten van te lijken NSURLConnection
, maar je zult in de loop van deze reeks dat leren NSURLSession
is modern, gemakkelijker te gebruiken en gebouwd met het oog op mobiel.
NSURLSession
?Voordat ik de verschillen tussen bespreek NSURLSession
en NSURLConnection
, het is een goed idee eerst wat beter te bekijken NSURLSession
is. Ondanks zijn naam, NSURLSession
is niet zomaar een klasse die je kunt gebruiken in een iOS- of OS X-applicatie. NSURLSession
is in de eerste plaats een technologie zoals NSURLConnection
is.
NSURLSession
en NSURLConnection
beide bieden een API voor interactie met verschillende protocollen, zoals HTTP
en HTTPS
. Het sessieobject, een instantie van de NSURLSession
klasse, is wat deze interactie beheert. Het is een zeer configureerbare container met een elegante API die een fijnmazig beheer mogelijk maakt. Het biedt functies die afwezig zijn in NSURLConnection
. Wat meer is, met NSURLSession
, je kunt taken uitvoeren die simpelweg niet mogelijk zijn NSURLConnection
, zoals het implementeren van privé browsen.
De basiseenheid van het werk om mee te werken NSURLSession
is de taak, een instantie van NSURLSessionTask
. Er zijn drie soorten taken, datataken, upload taken, en downloadtaken.
NSURLSessionDataTask
. Datataken worden gebruikt voor het opvragen van gegevens van een server, zoals JSON-gegevens. Het belangrijkste verschil met upload- en downloadtaken is dat ze gegevens rechtstreeks naar uw toepassing retourneren in plaats van door het bestandssysteem te gaan. De gegevens worden alleen in het geheugen opgeslagen.NSURLSessionUploadTask
is een subklasse van NSURLSessionDataTask
en gedraagt zich op dezelfde manier. Een van de belangrijkste verschillen met een normale gegevenstaak is dat uploadtaken kunnen worden gebruikt in een sessie die is gemaakt met een achtergrondsessies.NSURLSessionDownloadTask
, erven direct van NSURLSessionTask
. Het belangrijkste verschil met gegevenstaken is dat een downloadtaak zijn reactie rechtstreeks op een tijdelijk bestand schrijft. Dit verschilt nogal van een normale gegevenstaak die de reactie opslaat in het geheugen. Het is mogelijk om annuleren een downloadtaak en hervatten het op een later tijdstip.Zoals je je kunt voorstellen, asynchroniciteit is een sleutelbegrip in NSURLSession
. De NSURLSession
API retourneert gegevens door een voltooiingshandler aan te roepen of door de gedelegeerde van de sessie. De API van NSURLSession
werd ontworpen met flexibiliteit in het achterhoofd, zoals je een beetje later zult merken in deze tutorial.
Zoals ik eerder zei, NSURLSession
is zowel een technologie als een klasse waarmee je gaat werken. De NSURLSession
API bevat een aantal klassen, maar NSURLSession
is de belangrijkste component voor het verzenden van verzoeken en het ontvangen van antwoorden. De configuratie van het sessieobject wordt echter afgehandeld door een instantie van de NSURLSessionConfiguration
klasse. De NSURLSessionTask
klasse en zijn drie concrete subklassen zijn de werkers en worden altijd gebruikt in combinatie met een sessie omdat het de sessie is die de taakobjecten creëert.
Beide NSURLSession
en NSURLConnection
zijn sterk afhankelijk van het delegatiepatroon. De NSURLSessionDelegate
protocol declareert een handvol gedelegeerde methoden voor het afhandelen van gebeurtenissen op sessieniveau. tevens de NSURLSessionTask
klasse en subklassen verklaren elk een gedelegeerd protocol voor het afhandelen van gebeurtenissen op taakniveau.
De NSURLSession
API bouwt op klassen waar u al bekend mee bent, zoals NSURL
, NSURLRequest
, en NSURLResponse
.
Hoe werkt het NSURLSession
verschillen van NSURLConnection
? Dit is een belangrijke vraag, omdat NSURLConnection
wordt niet afgeschaft door Apple. Je kunt nog steeds gebruiken NSURLConnection
in uw projecten. Waarom zou je gebruiken? NSURLSession
?
Het eerste dat je moet begrijpen is dat het NSURLSession
instantie is het object dat het verzoek en het antwoord beheert. Dit is vergelijkbaar met hoe NSURLConnection
werkt, maar het belangrijkste verschil is dat de configuratie van de aanvraag wordt afgehandeld door het sessieobject, dat een object met een lange levensduur is. Dit gebeurt via de NSURLSessionConfiguration
klasse. Niet alleen biedt het de NSURLSession
API fijnmazige configuratie via de NSURLSessionConfiguration
klasse, moedigt het de scheiding van gegevens (verzoekstructuur) aan met metadata. De NSURLSessionDownloadTask
illustreert dit goed door direct het antwoord op het bestandssysteem te schrijven.
Authenticatie is eenvoudiger en eleganter verwerkt door NSURLSession
. De NSURLSession
API verwerkt verificatie op verbindingsbasis in plaats van op verzoekbasis, zoals NSURLConnection
doet. De NSURLSession
API maakt het ook handiger om HTTP-opties te bieden en elke sessie kan een afzonderlijke opslagcontainer hebben, afhankelijk van hoe u de sessie configureert.
In de introductie heb ik je dat verteld NSURLSession
biedt een moderne interface, die netjes met iOS 7 kan worden geïntegreerd. Een voorbeeld van deze integratie is NSURLSession
out-of-process-uploads en -downloads. NSURLSession
is geoptimaliseerd om de levensduur van de batterij te behouden, ondersteunt pauzeren, annuleren en hervatten van taken, evenals de multitasking-API van UIKit. Waar moet je niet van houden? NSURLSession
?
Een nieuwe API is het best te leren door te oefenen, dus het is tijd om Xcode op te starten en onze voeten nat te maken. Start Xcode 5, maak een nieuw project door te selecteren Nieuw> Project ... van de het dossier menu en selecteer de Toepassing enkele weergave sjabloon uit de lijst met iOS-applicatiesjablonen.
Geef je project een naam, zeg Xcode waar je het wilt opslaan en klik op creëren. Het is niet nodig om het project onder broncontrole te plaatsen.
Bij het werken met NSURLSession
, het is belangrijk om te begrijpen dat het sessieobject, een instantie van NSURLSession
, is de sterspeler. Het behandelt de verzoeken en antwoorden, configureert de verzoeken, beheert sessieopslag en status, enz. Het creëren van een sessie kan op verschillende manieren worden gedaan. De snelste manier om aan de slag te gaan is om te gebruiken NSURLSession
's sharedSession
klassemethode zoals hieronder getoond.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * -sessie = [NSURLSession sharedSession];
Maak een sessie
object in de view controller's viewDidLoad
methode zoals hierboven getoond. De sessie
object dat we hebben gemaakt, is prima voor ons voorbeeld, maar in de meeste gevallen wilt u waarschijnlijk een beetje meer flexibiliteit. De sessie
object dat we zojuist hebben gemaakt maakt gebruik van het globale NSURLCache
, NSHTTPCookieStorage
, en NSURLCredentialStorage
. Dit betekent dat het behoorlijk lijkt op een standaardimplementatie van NSURLConnection
.
Om de sessie
object om te gebruiken, laten we de iTunes Store Search API bevragen en zoeken naar software die door Apple is gemaakt. De iTunes Store Search API is eenvoudig te gebruiken en vereist geen authenticatie, wat het ideaal maakt voor ons voorbeeld.
Om de zoek-API te bevragen, moeten we een verzoek sturen naar https://itunes.apple.com/search
en geef enkele parameters door. Zoals we eerder zagen, bij het gebruik van de NSURLSession
API, een verzoek wordt vertegenwoordigd door een taak. Voor het doorzoeken van de zoek-API is alles wat we nodig hebben een gegevenstaak, een instantie van de NSURLSessionDataTask
klasse. Bekijk de bijgewerkte versie viewDidLoad
implementatie hieronder weergegeven.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * -sessie = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (NSData * data, NSURLResponse * response, NSError * error) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: data options: 0 error: nil]; NSLog (@ "% @", json); ];
Er zijn een aantal methoden beschikbaar om een taak te maken, maar het sleutelbegrip om te begrijpen is dat het sessie
object doet de daadwerkelijke creatie en configuratie van de taak. In dit voorbeeld roepen we aan dataTaskWithURL: completionHandler:
en geef het een instantie van NSURL
evenals een afhandelingsafhandelaar. De voltooiingshandler accepteert drie argumenten, de onbewerkte gegevens van het antwoord (NSData
), de antwoord object (NSURLResponse
), en een fout object (NSError
). Als het verzoek is gelukt, is het foutobject nul
. Omdat we weten dat het verzoek een JSON-reactie retourneert, maken we een fundament object van de gegevens
object dat we hebben ontvangen en registreer de uitvoer naar de console.
Het is belangrijk om te begrijpen dat de fout
object dat is doorgegeven aan de voltooiingshandler is alleen ingevuld, niet nul
, als de aanvraag is mislukt of een fout is opgetreden. Met andere woorden, als het verzoek is geretourneerd 404
reactie, het verzoek is geslaagd voor zover het de sessies betreft. De fout
object zal dan zijn nul
. Dit is een belangrijk concept om te begrijpen bij het werken met NSURLSession
en NSURLConnection
wat dat betreft.
Bouw het project en voer de applicatie uit in de iOS Simulator of op een fysiek apparaat en inspecteer de Xcode-console. Er wordt niets afgedrukt op de console. Wat ging er mis? Zoals ik eerder al zei, de NSURLSession
API ondersteunt pauzeren, annuleren en hervatten van taken of verzoeken. Dit gedrag lijkt op dat van NSOperation
en het kan u herinneren aan de AFNetworking-bibliotheek. Een taak heeft een staat
eigenschap die aangeeft of de taak is lopend (NSURLSessionTaskStateRunning
), geschorst (NSURLSessionTaskStateSuspended
), annuleren (NSURLSessionTaskStateCanceling
), of voltooid (NSURLSessionTaskStateCompleted
). Wanneer een sessieobject een taak maakt, start de taak zijn leven in de geschorst staat. Om de taak te starten, moeten we dit aan ons vertellen hervatten
door te bellen hervatten
op de taak. Werk het viewDidLoad
methode zoals hieronder getoond, voer de toepassing nog een keer uit en inspecteer de uitvoer in de console. Missie volbracht.
- (void) viewDidLoad [super viewDidLoad]; NSURLSession * -sessie = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (NSData * data, NSURLResponse * response, NSError * error) NSDictionary * json = [NSJSONSerialization JSONObjectWithData: data options: 0 error: nil]; NSLog (@ "% @", json); ]; [dataTask CV];
In het vorige voorbeeld hebben we een voltooiingshandler gebruikt om de reactie die we van het verzoek hebben ontvangen, te verwerken. Het is ook mogelijk om hetzelfde resultaat te bereiken door het uitvoeren van het taakdelegatieprotocol (len). Laten we eens kijken wat er nodig is om een afbeelding te downloaden door gebruik te maken van NSURLSession
en de NSURLSessionDownloadTask
.
Open MTViewController.h
en maak twee verkooppunten zoals hieronder getoond. We gebruiken de eerste outlet, een instantie van UIImageView
, om de gedownloade afbeelding weer te geven voor de gebruiker. De tweede uitlaat, een instantie van UIProgressView
, toont de voortgang van de downloadtaak.
#importeren@interface MTViewController: UIViewController @property (weak, nonatomic) IBOutlet UIImageView * imageView; @property (weak, nonatomic) IBOutlet UIProgressView * progressView; @einde
Open het belangrijkste storyboard van het project (Main.storyboard), sleep a UIImageView
bijvoorbeeld naar het aanzicht van de view controller, en verbind de outlet van de view controller die we zojuist hebben aangemaakt in het header-bestand van de view controller. Herhaal dit proces voor de voortgangsweergave.
In dit voorbeeld zullen we geen gebruik maken van de sharedSession
klassemethode, omdat we het moeten configureren sessie
object dat we zullen gebruiken om het verzoek te maken. Update de implementatie van viewDidLoad
zoals hieronder getoond.
- (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 CV];
Om te voorkomen dat er een compilerwaarschuwing opduikt, moet je ervoor zorgen dat je voldoet aan de MTViewController
klasse voor de NSURLSessionDelegate
en NSURLSessionDownloadDelegate
protocollen zoals hieronder getoond.
#import "MTViewController.h" @interface MTViewController ()@einde
In viewDidLoad
, we maken een instantie van de NSURLSessionConfiguration
klasse door het aanroepen van de defaultSessionConfiguration
klassemethode. Zoals vermeld in de documentatie, zal de sessie zich door het gebruik van de standaard sessieconfiguratie ongeveer als een instantie van NSURLConnection
in de standaardconfiguratie, wat prima is voor ons voorbeeld.
In dit voorbeeld maken we een NSURLSession
bijvoorbeeld door de sessionWithConfiguration: afgevaardigde: delegateQueue:
class methode en sla de sessionConfiguration
object dat we zojuist hebben gemaakt. We hebben de view controller ingesteld als sessiedelegate en geslaagd nul
als het derde argument. Je kunt het derde argument nu negeren. Het belangrijkste verschil met het vorige voorbeeld is dat we de sessie
afgevaardigde naar de view controller.
Om de afbeelding te downloaden, moeten we een downloadtaak maken. We doen dit door te bellen downloadTaskWithURL:
op de sessie
object, een instantie van passerend NSURL
, en bellen hervatten
op de downloadtaak. We hadden gebruik kunnen maken van een voltooiingshandler zoals we eerder deden, maar ik wil u de mogelijkheden tonen om in plaats daarvan een gemachtigde te gebruiken.
Om dit allemaal te laten werken, moeten we de drie gedelegeerde methoden van de NSURLSessionDownloadDelegate
protocol, URLSession: downloadTask: didFinishDownloadingToURL:
, URLSession: downloadTask: didResumeAtOffset: expectedTotalBytes:
, en URLSession: downloadTask: downloadTask didWriteData: totalBytesWritten: totalBytesExpectedToWrite:
. De implementatie van elke methode is vrij eenvoudig. Het is belangrijk op te merken dat we de gebruikersinterface op de hoofdthread moeten updaten met GCD (Grand Central Dispatch). Door te passeren nul
als het derde argument van sessionWithConfiguration: afgevaardigde: delegateQueue:
, het besturingssysteem heeft een achtergrondwachtrij voor ons gemaakt. Dit is prima, maar het betekent ook dat we ons ervan bewust moeten zijn dat de methoden van de gedelegeerde worden aangeroepen op een achtergrondthread in plaats van de rode draad. Bouw het project en voer de applicatie uit om het resultaat van ons harde werk te zien.
- (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) locatie NSData * data = [NSData dataWithContentsOfURL: location]; dispatch_async (dispatch_get_main_queue (), ^ [self.progressView sethidden: YES]; [self.imageView setImage: [UIImage imageWithData: data]];); - (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes - (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) byteswritte totalByteswritte: (int64_t) totalByteswritte totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite float progress = (dubbele) totalBytes Written / (double) totalBytesExpectedToWrite; dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setProgress: progress];);
Met deze twee voorbeelden moet u een basiskennis hebben van de grondbeginselen van de NSURLSession
API, hoe het zich verhoudt tot NSURLConnection
, en wat de voordelen zijn. In het volgende deel van deze serie zullen we kijken naar meer geavanceerde functies van NSURLSession
.