1. Code
  2. Mobile Development
  3. iOS Development

Vernetzung mit NSURLSession: Teil 1

Aus der Sicht eines Entwicklers ist die Einführung von NSURLSession eine der wichtigsten Änderungen in iOS 7 und OS X Mavericks.  Auch wenn NSURLSession auf den ersten Blick entmutigend erscheint, ist es wichtig, dass Sie wissen, was es ist, wie es sich auf NSURLConnection bezieht und was die Unterschiede sind.  In dieser Serie werde ich Sie durch die Grundlagen von NSURLSession führen, damit Sie diese neue Technologie in Ihren eigenen Anwendungen nutzen können.
Scroll to top
This post is part of a series called Working with NSURLSession.
Networking with NSURLSession: Part 2

German (Deutsch) translation by Federicco Ancie (you can also view the original English article)

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


Warum NSURLConnection ersetzen?

Die erste Frage, die Sie sich vielleicht stellen, ist, warum Apple die Einführung von NSURLSession für notwendig hielt, während wir mit NSURLConnection absolut zufrieden sind.  Die eigentliche Frage ist, ob Sie mit NSURLConnection zufrieden sind. Erinnerst du dich an die Zeit, als du NSURLConnection beschimpft hast?  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 hinsichtlich ihrer Funktionsweise vieles gemeinsam haben, unterscheiden sie sich grundsätzlich.  Apple hat NSURLSession entwickelt, um den allgemeinen Konzepten von NSURLConnection zu ähneln. Im Verlauf dieser Serie erfahren Sie jedoch, dass NSURLSession modern, benutzerfreundlicher und mobiler ist.


Was ist NSURLSession?

Bevor ich die Unterschiede zwischen NSURLSession und NSURLConnection erörtere, ist es eine gute Idee, zunächst einmal genauer zu verstehen, was NSURLSession ist.  Trotz seines Namens ist NSURLSession nicht nur eine andere Klasse, die Sie in einer iOS- oder OS X-Anwendung verwenden können.  NSURLSession ist in erster Linie eine Technologie, genau wie NSURLConnection.

Sitzungen sind Container

NSURLSession und NSURLConnection bieten beide eine API für die Interaktion mit verschiedenen Protokollen wie HTTP und HTTPS.  Das Session-Objekt, eine Instanz der 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 NSURLConnection nicht vorhanden sind.  Darüber hinaus können Sie mit NSURLSession Aufgaben ausführen, die mit NSURLConnection nicht möglich sind, z. B. die Implementierung des privaten Browsens.

Aufgaben

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

  • Meistens werden Datentasks verwendet, bei denen es sich um NSURLSessionDataTask-Instanzen handelt. 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.  Die 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 herunter, Instanzen von NSURLSessionDownloadTask, die direkt von NSURLSessionTask erben.  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.  Sie können eine Download-Aufgabe abbrechen und zu einem späteren Zeitpunkt fortsetzen.

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

Die Familie treffen

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

Delegation

Sowohl NSURLSession als auch NSURLConnection hängen stark vom Delegierungsmuster ab. Das NSURLSessionDelegate-Protokoll deklariert eine Handvoll Delegatmethoden für die Behandlung von Ereignissen auf Sitzungsebene.  Darüber hinaus deklarieren die NSURLSessionTask-Klasse und die Unterklassen jeweils ein Delegatenprotokoll für die Behandlung von Ereignissen auf Taskebene.

Alte Freunde

Die NSURLSession-API baut auf Klassen auf, mit denen Sie bereits vertraut sind, z. B. NSURL, NSURLRequest und NSURLResponse.


Was sind die Unterschiede?

Wie unterscheidet sich NSURLSession von NSURLConnection?  Dies ist eine wichtige Frage, da NSURLConnection von Apple nicht verworfen wird.  Sie können NSURLConnection weiterhin in Ihren Projekten verwenden.  Warum sollten Sie NSURLSession verwenden?

Das erste, was Sie verstehen müssen, ist, dass die NSURLSession-Instanz das Objekt ist, das die Anforderung und die Antwort verwaltet.  Dies ähnelt der Funktionsweise von NSURLConnection, der Hauptunterschied besteht jedoch darin, dass die Konfiguration der Anforderung vom Sitzungsobjekt verarbeitet wird, das ein langlebiges Objekt ist.  Dies erfolgt über die Klasse NSURLSessionConfiguration.  Sie bietet nicht nur die fein abgestufte Konfiguration der NSURLSession-API über die Klasse NSURLSessionConfiguration, sondern unterstützt auch die Trennung von Daten (Anforderungshauptteil) von Metadaten.  Die NSURLSessionDownloadTask veranschaulicht dies gut, indem die Antwort direkt in das Dateisystem geschrieben wird.

Die Authentifizierung wird durch NSURLSession einfacher und eleganter gehandhabt.  Die NSURLSession-API behandelt die Authentifizierung auf Verbindungsbasis und nicht auf Anfrage, wie dies bei NSURLConnection der Fall ist.  Die NSURLSession-API macht es auch bequemer, HTTP-Optionen bereitzustellen, und jede Sitzung kann einen separaten Speichercontainer haben, abhängig davon, wie Sie die Sitzung konfigurieren.

In der Einführung habe ich Ihnen gesagt, dass NSURLSession eine moderne Schnittstelle bietet, die sich nahtlos in iOS 7 integriert. Ein Beispiel für diese Integration sind die Out-of-Process-Uploads und -Downloads von NSURLSessionNSURLSession wurde optimiert, um die Lebensdauer der Batterie zu erhalten, unterstützt das Anhalten, Abbrechen und Wiederaufnehmen von Aufgaben sowie die Multitasking-API von UIKit.  Was ist an NSURLSession nicht zu lieben?


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 im Menü Datei die Option Neu > Projekt auswählen, und wählen Sie in der Liste der iOS-Anwendungsvorlagen die Vorlage Single View Application aus.

Create a new project in Xcode 5.Create a new project in Xcode 5.Create a new project in Xcode 5.

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.

Configure the project.Configure the project.Configure the project.

Schritt 2: Erstellen Sie ein Sitzungsobjekt

Bei der Arbeit mit NSURLSession ist es wichtig zu verstehen, dass das Sitzungsobjekt, eine Instanz von NSURLSession, der Star-Player ist.  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 der sharedSession-Klassenmethode von NSURLSession, wie unten gezeigt.

1
2
- (void)viewDidLoad {
3
    [super viewDidLoad];
4
5
    NSURLSession *session = [NSURLSession sharedSession];
6
}

Erstellen Sie ein Session-Objekt in der viewDidLoad-Methode des View-Controllers (siehe oben).  Das von uns erstellte session objekt ist für unser Beispiel in Ordnung, aber in den meisten Fällen möchten Sie wahrscheinlich etwas mehr Flexibilität.  Das soeben erstellte session objekt verwendet den globalen NSURLCache, NSHTTPCookieStorage und NSURLCredentialStorage.  Dies bedeutet, dass es einer Standardimplementierung von NSURLConnection ziemlich ähnlich ist.

Schritt 3: Erstellen Sie eine Datenaufgabe

Um das session objekt zu verwenden, lassen Sie uns die iTunes Store Search API abfragen und nach Software von Apple 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 Sie eine Anfrage an https://itunes.apple.com/search  senden und einige Parameter übergeben.  Wie wir bereits gesehen haben, wird bei Verwendung der NSURLSession-API eine Anforderung durch eine Aufgabe dargestellt.  Um die Such-API abzufragen, benötigen wir lediglich eine Datentask, eine Instanz der Klasse NSURLSessionDataTask.  Schauen Sie sich die aktualisierte viewDidLoad-Implementierung unten an.

1
2
- (void)viewDidLoad {
3
    [super viewDidLoad];
4
5
    NSURLSession *session = [NSURLSession sharedSession];
6
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
7
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
8
        NSLog(@"%@", json);
9
    }];
10
}

Es gibt eine Reihe von Methoden, um eine Aufgabe zu erstellen, aber das Schlüsselkonzept ist, dass das session objekt die eigentliche Erstellung und Konfiguration der Aufgabe vornimmt.  In diesem Beispiel rufen wir dataTaskWithURL: completionHandler: auf und übergeben eine Instanz von NSURL sowie einen Completion-Handler.  Der Completion-Handler akzeptiert drei Argumente, die Rohdaten der Antwort (NSData), das Antwortobjekt (NSURLResponse) und ein Fehlerobjekt (NSError).  Wenn die Anforderung erfolgreich ist, ist das Fehlerobjekt null.  Da wir wissen, dass die Anforderung eine JSON-Antwort zurückgibt, erstellen wir ein Foundation-Objekt aus dem data objekt, das wir erhalten haben, und protokollieren die Ausgabe in der Konsole.

Es ist wichtig zu verstehen, dass das an den Beendigungshandler übergebene error objekt nur dann aufgefüllt wird, wenn die Anforderung fehlschlägt oder ein null aufgetreten ist.  Mit anderen Worten, wenn die Anfrage eine Antwort von 404 zurückgegeben hat, war die Anfrage in Bezug auf die Sitzungen erfolgreich.  Das error objekt ist dann null.  Dies ist ein wichtiges Konzept, das bei der Arbeit mit NSURLSession und NSURLConnection zu berücksichtigen ist.

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 bereits erwähnt, unterstützt die NSURLSession-API das Anhalten, Abbrechen und Wiederaufnehmen von Aufgaben oder Anforderungen.  Dieses Verhalten ähnelt dem von NSOperation und erinnert Sie möglicherweise an die AFNetworking-Bibliothek.  Eine Task verfügt über eine State-Eigenschaft, die angibt, ob die Task ausgeführt wird (NSURLSessionTaskStateRunning), ausgesetzt (NSURLSessionTaskStateSuspended), abgebrochen (NSURLSessionTaskStateCanceling) oder abgeschlossen (NSURLSessionTaskStateCompleted) ist.  Wenn ein Sitzungsobjekt eine Aufgabe erstellt, beginnt die Lebensdauer der Aufgabe im angehaltenen Zustand.  Um die Aufgabe zu starten, müssen Sie ihr sagen, dass sie fortfahren soll, indem Sie die Funktion "Wiederaufnahme" für die Aufgabe aufrufen.  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.

1
2
- (void)viewDidLoad {
3
    [super viewDidLoad];
4
5
    NSURLSession *session = [NSURLSession sharedSession];
6
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
7
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
8
        NSLog(@"%@", json);
9
    }];
10
11
    [dataTask resume];
12
}

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.  Sehen wir uns an, was zum Herunterladen eines Bildes erforderlich ist, indem Sie NSURLSession und NSURLSessionDownloadTask nutzen.

Schritt 1: Erstellen Sie die Benutzeroberfläche

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

1
2
#import <UIKit/UIKit.h>

3
4
@interface MTViewController : UIViewController
5
6
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
7
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
8
9
@end

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

Configure the application's user interface.Configure the application's user interface.Configure the application's user interface.

Schritt 2: Erstellen Sie eine Download-Aufgabe

In diesem Beispiel wird die Klassenmethode sharedSession nicht verwendet, da das session objekt konfiguriert werden muss, das für die Anforderung verwendet wird.  Aktualisieren Sie die Implementierung von viewDidLoad wie unten gezeigt.

1
2
- (void)viewDidLoad {
3
    [super viewDidLoad];
4
5
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
6
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
7
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://cdn.tutsplus.com/mobile/uploads/2013/12/sample.jpg"]];
8
    [downloadTask resume];
9
}

Stellen Sie sicher, dass die MTViewController-Klasse mit den Protokollen NSURLSessionDelegate und NSURLSessionDownloadDelegate übereinstimmt, um zu verhindern, dass Compiler-Warnungen angezeigt werden.

1
2
#import "MTViewController.h"

3
4
@interface MTViewController () <NSURLSessionDelegate, NSURLSessionDownloadDelegate>
5
6
@end

In viewDidLoad erstellen wir eine Instanz der NSURLSessionConfiguration-Klasse, indem wir die Klassenmethode defaultSessionConfiguration aufrufen.  Wie in der Dokumentation angegeben, verhält sich die Sitzung bei Verwendung der Standardsitzungskonfiguration in ihrer Standardkonfiguration wie eine Instanz von NSURLConnection. Dies ist in unserem Beispiel ausreichend.

In diesem Beispiel erstellen wir eine NSURLSession-Instanz, indem wir die sessionWithConfiguration: delegate: delegateQueue:-Klassenmethode aufrufen und das vor einem Moment erstellte sessionConfiguration-Objekt übergeben.  Wir setzen den View Controller als Sitzungsdelegierten und übergeben als drittes Argument Null.  Sie können das dritte Argument vorerst ignorieren.  Der Hauptunterschied zum vorherigen Beispiel besteht darin, dass wir den Delegierten der session auf den View-Controller setzen.

Um das Bild herunterzuladen, müssen Sie eine Download-Aufgabe erstellen.  Dazu rufen wir downloadTaskWithURL: für das session objekt auf, übergeben eine Instanz von NSURL und rufen das Resume für die Download-Task auf.  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

Um dies zu erreichen, müssen Sie die drei Delegat-Methoden des NSURLSessionDownloadDelegate-Protokolls URLSession: downloadTask: didFinDownloadingToURL :, URLSession: downloadTask: didResumeAtOffset: expectedTotalBytes :, und URLSession:downloadTask:downloadTask didWriteData:totalBytesWritten:totalBytesExpectedToWrite:.  Die Implementierung jeder Methode ist recht einfach.  Beachten Sie, dass die Benutzeroberfläche des Hauptthreads mithilfe von GCD (Grand Central Dispatch) aktualisiert werden muss.  Durch die Übergabe von nil als drittes Argument von sessionWithConfiguration: delegate: delegateQueue: erstellt das Betriebssystem eine Hintergrundwarteschlange für uns.  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.

1
2
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
3
    NSData *data = [NSData dataWithContentsOfURL:location];
4
5
    dispatch_async(dispatch_get_main_queue(), ^{
6
        [self.progressView setHidden:YES];
7
        [self.imageView setImage:[UIImage imageWithData:data]];
8
    });
9
}
10
11
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
12
13
}
14
15
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
16
    float progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
17
18
    dispatch_async(dispatch_get_main_queue(), ^{
19
        [self.progressView setProgress:progress];
20
    });
21
}

Fazit

Mit diesen beiden Beispielen sollten Sie ein grundlegendes Verständnis der Grundlagen der NSURLSession-API, ihres Vergleichs mit NSURLConnection und ihrer Vorteile besitzen.  Im nächsten Teil dieser Serie werden wir uns mit den erweiterten Funktionen von NSURLSession beschäftigen.