Vernetzung mit NSURLSession Teil 1

Aus der Sicht eines Entwicklers ist die Einführung von, eine der wichtigsten Änderungen in iOS 7 und OS X Mavericks NSURLSession. Obwohl NSURLSession mag auf den ersten Blick entmutigend erscheinen, es ist wichtig, dass Sie verstehen, was es ist und wie es sich bezieht NSURLConnection, und was sind die unterschiede. In dieser Serie werde ich Sie durch die Grundlagen von führen NSURLSession So können Sie diese neue Technologie in Ihren eigenen Anwendungen nutzen.


Warum ersetzen? NSURLConnection?

Die erste Frage, die Sie sich vielleicht stellen, ist, warum Apple es für notwendig hielt, ihn vorzustellen NSURLSession während wir vollkommen zufrieden sind mit NSURLConnection. Die eigentliche Frage ist, ob du sind glücklich mit NSURLConnection. Erinnerst du dich an die Zeit, als du fluchst und Dinge würfst? NSURLConnection? Die meisten Cocoa-Entwickler waren an diesem Ort, weshalb sich Apple dafür entschieden hat, wieder an das Zeichenbrett zu gehen und eine elegantere Lösung zu entwickeln, die besser für das moderne Web geeignet ist.

Obwohl NSURLSession und NSURLConnection Sie haben viel gemeinsam in Bezug auf ihre Funktionsweise. Grundsätzlich sind sie sehr unterschiedlich. Apple erstellt NSURLSession den allgemeinen Begriffen von NSURLConnection, Aber das werden Sie im Laufe dieser Serie lernen NSURLSession ist modern, benutzerfreundlicher und mobiler gebaut.


Was ist NSURLSession?

Bevor ich die Unterschiede bespreche NSURLSession und NSURLConnection, es ist eine gute idee, zuerst was näher zu betrachten NSURLSession ist. Trotz seines Namens, NSURLSession ist nicht nur eine andere Klasse, die Sie in einer iOS- oder OS X-Anwendung verwenden können. NSURLSession ist in erster Linie eine Technologie wie NSURLConnection ist.

Sitzungen sind Container

NSURLSession und NSURLConnection Beide bieten eine API für die Interaktion mit verschiedenen Protokollen, z HTTP und HTTPS. Das Session-Objekt, eine Instanz von NSURLSession Klasse, verwaltet diese Interaktion. Es ist ein hoch konfigurierbarer Container mit einer eleganten API, die eine feinkörnige Steuerung ermöglicht. Es bietet Funktionen, die in fehlen NSURLConnection. Was ist mehr mit NSURLSession, Sie können Aufgaben erledigen, die mit einfach nicht möglich sind NSURLConnection, wie privates Browsing implementieren.

Aufgaben

Die grundlegende Arbeitseinheit bei der Arbeit mit NSURLSession ist die Aufgabe, eine Instanz von NSURLSessionTask. Es gibt drei Arten von Aufgaben, Datenaufgaben, Aufgaben hochladen, und Aufgaben herunterladen.

  • Meist werden Sie Datenaufgaben verwenden, die Instanzen von sind NSURLSessionDataTask. Datentasks werden zum Anfordern von Daten von einem Server verwendet, z. B. JSON-Daten. Der Hauptunterschied bei Upload- und Download-Tasks besteht darin, dass Daten direkt an Ihre Anwendung zurückgegeben werden, anstatt das Dateisystem zu durchlaufen. Die Daten werden nur im Speicher gespeichert.
  • Wie der Name schon sagt, werden Upload-Aufgaben verwendet, um Daten an ein Remote-Ziel hochzuladen. Das NSURLSessionUploadTask ist eine Unterklasse von NSURLSessionDataTask und verhält sich auf ähnliche Weise. Einer der Hauptunterschiede zu einer normalen Datenaufgabe besteht darin, dass Upload-Aufgaben in einer Sitzung verwendet werden können, die mit einer Hintergrundsitzungskonfiguration erstellt wurde.
  • Laden Sie Aufgaben, Instanzen von herunter NSURLSessionDownloadTask, erben direkt von NSURLSessionTask. Der wichtigste Unterschied bei Datenaufgaben besteht darin, dass eine Download-Aufgabe ihre Antwort direkt in eine temporäre Datei schreibt. Dies unterscheidet sich stark von einer normalen Datenaufgabe, die die Antwort im Speicher speichert. Es ist möglich zu stornieren eine Download-Aufgabe und fortsetzen es zu einem späteren Zeitpunkt.

Wie Sie sich vorstellen können, ist Asynchronität ein Schlüsselbegriff in NSURLSession. Das NSURLSession Die API gibt Daten zurück, indem ein Beendigungshandler oder der Delegat der Sitzung aufgerufen wird. Die API von NSURLSession wurde im Hinblick auf Flexibilität konzipiert, wie Sie später in diesem Tutorial feststellen werden.

Die Familie treffen

Wie ich schon erwähnt habe, NSURLSession ist sowohl eine Technologie als auch eine Klasse, mit der Sie arbeiten werden. Das NSURLSession API enthält jedoch eine Reihe von Klassen NSURLSession ist die Schlüsselkomponente, die Anforderungen sendet und Antworten empfängt. Die Konfiguration des Sitzungsobjekts wird jedoch von einer Instanz von verwaltet NSURLSessionConfiguration Klasse. Das NSURLSessionTask Die Klasse und ihre drei konkreten Unterklassen sind die Worker und werden immer in Verbindung mit einer Sitzung verwendet, da sie die Aufgabenobjekte erstellen.

Delegation

Beide NSURLSession und NSURLConnection verlassen sich stark auf das Delegationsmuster. Das NSURLSessionDelegate Das Protokoll deklariert eine Handvoll Delegatmethoden für die Behandlung von Ereignissen auf Sitzungsebene. zusätzlich NSURLSessionTask Klassen und Unterklassen deklarieren jeweils ein Delegatenprotokoll zur Behandlung von Ereignissen auf Taskebene.

Alte Freunde

Das NSURLSession API baut auf Klassen auf, mit denen Sie bereits vertraut sind, wie z NSURL, NSURLAnfrage, und NSURLResponse.


Was sind die Unterschiede?

Wie geht das NSURLSession unterscheiden sich von NSURLConnection? Dies ist eine wichtige Frage, weil NSURLConnection wird nicht von Apple abgelehnt. Sie können immer noch verwenden NSURLConnection in Ihren Projekten. Warum sollten Sie verwenden? NSURLSession?

Das erste, was zu verstehen ist, ist das NSURLSession Instanz ist das Objekt, das die Anforderung und die Antwort verwaltet. Dies ist ähnlich wie NSURLConnection funktioniert, der Hauptunterschied besteht jedoch darin, dass die Konfiguration der Anforderung vom Sitzungsobjekt, einem langlebigen Objekt, gehandhabt wird. Dies geschieht durch die NSURLSessionConfiguration Klasse. Es bietet nicht nur die NSURLSession Fein abgestimmte API-Konfiguration über die NSURLSessionConfiguration Diese Klasse fördert die Trennung von Daten (Anfragetext) und Metadaten. Das NSURLSessionDownloadTask veranschaulicht dies gut, indem die Antwort direkt in das Dateisystem geschrieben wird.

Die Authentifizierung ist einfacher und eleganter durch NSURLSession. Das NSURLSession Die API behandelt die Authentifizierung auf Verbindungsbasis und nicht auf Anfrage, wie z NSURLConnection tut. Das NSURLSession Die API macht es auch bequemer, HTTP-Optionen bereitzustellen, und jede Sitzung kann einen separaten Speichercontainer haben, je nachdem, wie Sie die Sitzung konfigurieren.

In der Einleitung habe ich Ihnen das gesagt NSURLSession bietet eine moderne Benutzeroberfläche, die sich nahtlos in iOS 7 integriert. Ein Beispiel für diese Integration ist NSURLSessionOut-of-Process-Uploads und -Downloads. NSURLSession wurde optimiert, um die Akkulaufzeit zu erhalten, unterstützt das Anhalten, Abbrechen und Wiederaufnehmen von Aufgaben sowie die Multitasking-API von UIKit. Was soll man nicht lieben? NSURLSession?


Nasse Füße bekommen

Schritt 1: Projekt einrichten

Eine neue API lässt sich am besten durch Übung erlernen, also ist es an der Zeit, Xcode zu starten und die Füße nass zu machen. Starten Sie Xcode 5, erstellen Sie ein neues Projekt, indem Sie auswählen Neu> Projekt… von dem Datei Menü und wählen Sie die Einzelansicht-Anwendung Vorlage aus der Liste der iOS-Anwendungsvorlagen.


Geben Sie Ihrem Projekt einen Namen, teilen Sie Xcode mit, wo Sie es speichern möchten, und klicken Sie auf Erstellen. Das Projekt muss nicht unter Quellcodeverwaltung gestellt werden.


Schritt 2: Erstellen Sie ein Sitzungsobjekt

Bei der Arbeit mit NSURLSession, Es ist wichtig zu verstehen, dass das Sitzungsobjekt eine Instanz von NSURLSession, ist der Starspieler. Es verarbeitet die Anforderungen und Antworten, konfiguriert die Anforderungen, verwaltet den Speicher und den Status der Sitzung usw. Das Erstellen einer Sitzung kann auf verschiedene Arten erfolgen. Der schnellste Weg zum Einstieg ist die Verwendung NSURLSession's sharedSession Klassenmethode wie unten gezeigt.

 - (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; 

Ein ... kreieren Session Objekt im View Controller viewDidLoad Methode wie oben gezeigt. Das Session Das von uns erstellte Objekt ist für unser Beispiel in Ordnung, aber Sie möchten wahrscheinlich in den meisten Fällen etwas mehr Flexibilität. Das Session Das Objekt, das wir gerade erstellt haben, verwendet das Globale NSURLCache, NSHTTPCookieStorage, und NSURLCredentialStorage. Dies bedeutet, dass es ähnlich funktioniert wie eine Standardimplementierung von NSURLConnection.

Schritt 3: Erstellen Sie eine Datenaufgabe

Um das zu setzen Session Zu verwendendes Objekt, lassen Sie uns die iTunes Store Search API abfragen und nach von Apple erstellter Software suchen. Die iTunes Store Search API ist einfach zu verwenden und erfordert keine Authentifizierung. Dies macht sie ideal für unser Beispiel.

Um die Such-API abzufragen, müssen wir eine Anfrage an senden https://itunes.apple.com/search und einige Parameter übergeben. Wie wir zuvor gesehen haben, bei der Verwendung von NSURLSession API, eine Anforderung wird durch eine Aufgabe dargestellt. Um die Such-API abzufragen, benötigen wir lediglich eine Datenaufgabe, eine Instanz der NSURLSessionDataTask Klasse. Schauen Sie sich das aktualisierte an viewDidLoad Implementierung unten gezeigt.

 - (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [Sitzung dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (NSData * -Daten, NSURLResponse * -Antwort, NSError * -Fehler)  NSDictionary * json = [NSJSONSerialization JSONObjectWithData: Datenoptionen: 0 Fehler: Null]; NSLog (@ "% @", json); ]; 

Es gibt eine Reihe von Methoden, um eine Aufgabe zu erstellen Session object übernimmt die eigentliche Erstellung und Konfiguration der Aufgabe. In diesem Beispiel rufen wir auf dataTaskWithURL: completionHandler: und gib ein Beispiel von NSURL sowie einen Completion-Handler. Der Beendigungs-Handler akzeptiert drei Argumente, den Rohdaten der Antwort (NSData), das Antwortobjekt (NSURLResponse), und ein Fehlerobjekt (NSError). Wenn die Anforderung erfolgreich ist, wird das Fehlerobjekt angezeigt Null. Da wir wissen, dass die Anforderung eine JSON-Antwort zurückgibt, erstellen wir eine Stiftung Objekt aus der Daten Objekt, das wir erhalten haben, und protokolliert die Ausgabe in der Konsole.

Es ist wichtig zu verstehen, dass die Error Das an den Completion-Handler übergebene Objekt wird nur gefüllt, nicht Null, wenn die Anforderung fehlgeschlagen ist oder ein Fehler aufgetreten ist. Mit anderen Worten, wenn die Anforderung zurückgegeben wird a 404 Antwort, die Anfrage war in Bezug auf die Sitzungen erfolgreich. Das Error Objekt wird dann sein Null. Dies ist ein wichtiges Konzept, das bei der Arbeit zu verstehen ist NSURLSession und NSURLConnection für diese Angelegenheit.

Erstellen Sie das Projekt, führen Sie die Anwendung im iOS-Simulator oder auf einem physischen Gerät aus und überprüfen Sie die Xcode-Konsole. Auf der Konsole wird nichts gedruckt. Was schief gelaufen ist? Wie ich bereits erwähnt habe NSURLSession Die API unterstützt das Anhalten, Abbrechen und Wiederaufnehmen von Aufgaben oder Anforderungen. Dieses Verhalten ähnelt dem von NSOperation und es erinnert Sie möglicherweise an die AFNetworking-Bibliothek. Eine Aufgabe hat eine Zustand Eigenschaft, die angibt, ob die Aufgabe ist Laufen (NSURLSessionTaskStateRunning), suspendiert (NSURLSessionTaskStateSuspended), abbrechen (NSURLSessionTaskStateCanceling), oder abgeschlossen (NSURLSessionTaskStateCompleted). Wenn ein Sitzungsobjekt eine Aufgabe erstellt, beginnt die Aufgabe im suspendiert Zustand. Um die Aufgabe zu starten, müssen wir es mitteilen fortsetzen durch anrufen fortsetzen auf die aufgabe. Aktualisieren Sie die viewDidLoad Methode wie unten gezeigt, führen Sie die Anwendung noch einmal aus und überprüfen Sie die Ausgabe in der Konsole. Mission erfüllt.

 - (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [Sitzung dataTaskWithURL: [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"] completionHandler: ^ (NSData * -Daten, NSURLResponse * -Antwort, NSError * -Fehler)  NSDictionary * json = [NSJSONSerialization JSONObjectWithData: Datenoptionen: 0 Fehler: Null]; NSLog (@ "% @", json); ]; [dataTask Lebenslauf]; 

Herunterladen einer Remote-Ressource

Im vorherigen Beispiel haben wir einen Completion-Handler verwendet, um die Antwort zu verarbeiten, die wir von der Anfrage erhalten haben. Es ist auch möglich, das gleiche Ergebnis zu erzielen, indem das Task Delegate-Protokoll implementiert wird. Mal sehen, was es braucht, um ein Bild herunterzuladen NSURLSession und das NSURLSessionDownloadTask.

Schritt 1: Erstellen Sie die Benutzeroberfläche

Öffnen MTViewController.h und erstellen Sie zwei Auslässe wie unten gezeigt. Wir verwenden den ersten Ausgang, eine Instanz von UIImageView, um das heruntergeladene Bild dem Benutzer anzuzeigen. Der zweite Auslass, eine Instanz von UIProgressView, zeigt den Fortschritt der Download-Aufgabe an.

 #einführen  @interface MTViewController: UIViewController @property (schwach, nicht atomar) IBOutlet UIImageView * imageView; @ property (schwach, nicht atomar) IBOutlet UIProgressView * progressView; @Ende

Öffnen Sie das Haupt-Storyboard des Projekts (Hauptplatine), ziehen Sie eine UIImageView Instanz in die Ansicht des View-Controllers ein, und verbinden Sie den soeben erstellten Ausgang des View-Controllers in der Header-Datei des View-Controllers. Wiederholen Sie diesen Vorgang für die Fortschrittsansicht.


Schritt 2: Erstellen Sie eine Download-Aufgabe

In diesem Beispiel machen wir keinen Gebrauch von sharedSession Klassenmethode, weil wir das konfigurieren müssen Session Objekt, das wir verwenden, um die Anfrage zu stellen. Aktualisieren Sie die Implementierung von viewDidLoad Wie nachfolgend dargestellt.

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

Um zu verhindern, dass eine Warnung des Compilers angezeigt wird, müssen Sie die entsprechende Einstellung vornehmen MTViewController Klasse zum NSURLSessionDelegate und NSURLSessionDownloadDelegate Protokolle wie unten gezeigt.

 #import "MTViewController.h" @interface MTViewController ()  @Ende

Im viewDidLoad, wir erstellen eine Instanz von NSURLSessionConfiguration Klasse durch Aufrufen der defaultSessionConfiguration Klassenmethode. Wie in der Dokumentation angegeben, verhält sich die Sitzung bei Verwendung der Standardsitzungskonfiguration wie eine Instanz von NSURLConnection in der Standardkonfiguration, was für unser Beispiel in Ordnung ist.

In diesem Beispiel erstellen wir eine NSURLSession Instanz durch Aufrufen der sessionWithConfiguration: delegate: delegateQueue: Klassenmethode und übergeben Sie die sessionConfiguration Objekt, das wir vor einem Moment erstellt haben. Wir setzen den View Controller als Sitzungsdelegierten und bestanden Null als drittes Argument. Sie können das dritte Argument vorerst ignorieren. Der Hauptunterschied zum vorherigen Beispiel besteht darin, dass wir das setzen SessionDelegierte an den View Controller.

Um das Bild herunterzuladen, müssen Sie eine Download-Aufgabe erstellen. Wir machen das, indem wir anrufen downloadTaskWithURL: auf der Session Objekt, das eine Instanz von NSURL, und anrufen fortsetzen auf der Download-Aufgabe. Wir hätten einen Fertigstellungs-Handler wie zuvor verwenden können, aber ich möchte Ihnen die Möglichkeiten zeigen, stattdessen einen Delegierten zu verwenden.

Schritt 3: Implementieren Sie das Delegate-Protokoll

Damit dies alles funktioniert, müssen wir die drei Delegatmethoden des NSURLSessionDownloadDelegate Protokoll, URLSession: downloadTask: didFinishDownloadingToURL:, URLSession: downloadTask: didResumeAtOffset: expectedTotalBytes:, und URLSession: downloadTask: downloadTask didWriteData: totalBytesWritten: totalBytesExpectedToWrite:. Die Implementierung jeder Methode ist recht einfach. Es ist wichtig zu wissen, dass wir die Benutzeroberfläche des Hauptthreads mit GCD (Grand Central Dispatch) aktualisieren müssen. Durchgehen Null als drittes Argument von sessionWithConfiguration: delegate: delegateQueue:, Das Betriebssystem hat eine Hintergrundwarteschlange für uns erstellt. Dies ist in Ordnung, bedeutet aber auch, dass wir wissen müssen, dass die Delegat-Methoden in einem Hintergrundthread anstelle des Hauptthreads aufgerufen werden. Erstellen Sie das Projekt und führen Sie die Anwendung aus, um das Ergebnis unserer harten Arbeit zu sehen.

 - (void) URLSession: (NSURLSession *) Sitzung downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) location NSData * data = [NSData dataWithContentsOfURL: location]; dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setHidden: YES]; [self.imageView setImage: [UIImage imageWithData: data]];);  - (void) URLSession: (NSURLSession *) Sitzung downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) erwartetTotalBytes  - (void) URLSession: (NSURLSachr. downloadTask didWriteData: (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesWritten totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite float progress = (doppelt) totalBytesWritten / (double) totalBytesExpt. dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setProgress: progress];); 

Fazit

Mit diesen zwei Beispielen sollten Sie ein grundlegendes Verständnis für die Grundlagen der NSURLSession API, wie es zu vergleichen ist NSURLConnection, und was sind die Vorteile. Im nächsten Teil dieser Serie werden wir uns mit den fortgeschritteneren Funktionen von NSURLSession.