Netwerken met NSURLSession deel 1

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.


Waarom vervangen 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.


Wat is 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.

Sessies zijn Containers

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.

taken

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.

  • U zult meestal datataken gebruiken, die voorbeelden zijn van 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.
  • Zoals de naam al aangeeft, worden uploadtaken gebruikt om gegevens naar een externe bestemming te uploaden. De 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.
  • Downloadtaken, exemplaren van 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.

Ontmoet de familie

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.

Delegatie

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.

Oude vrienden

De NSURLSession API bouwt op klassen waar u al bekend mee bent, zoals NSURL, NSURLRequest, en NSURLResponse.


Wat zijn de verschillen?

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 NSURLSessionout-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?


Je voeten nat krijgen

Stap 1: Projectinstellingen

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.


Stap 2: maak een sessieobject

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.

Stap 3: Maak een gegevenstaak

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]; 

Remote Resource downloaden

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.

Stap 1: maak de gebruikersinterface

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.


Stap 2: Maak een downloadtaak

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 sessieafgevaardigde 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.

Stap 3: Implementeer het delegatieprotocol

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];); 

Conclusie

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.