Vernetzung mit NSURLSession Teil 2

In der vorherigen Anleitung habe ich Sie vorgestellt NSURLSession. Ich habe über die Vorteile gesprochen NSURLConnection und wie man es benutzt NSURLSession Für einfache Aufgaben wie das Abrufen von Daten von einem Webdienst und das Herunterladen eines Bildes aus dem Web. In diesem Tutorial betrachten wir die Konfigurationsoptionen von NSURLSession und wie Sie eine Download-Aufgabe abbrechen und fortsetzen können. Wir haben viel zu tun, also fangen wir an.


Sitzungskonfiguration

Wie wir im vorherigen Tutorial gesehen haben, eine Sitzung, eine Instanz von NSURLSession, ist ein konfigurierbarer Container zum Einfügen von Netzwerkanforderungen. Die Konfiguration der Sitzung wird von einer Instanz von verwaltet NSURLSessionConfiguration.

Ein Sitzungskonfigurationsobjekt ist nichts anderes als ein Wörterbuch mit Eigenschaften, das definiert, wie sich die Sitzung verhält, an die es gebunden ist. Eine Sitzung verfügt über ein Sitzungskonfigurationsobjekt, das die Cookie-, Sicherheits- und Cache-Richtlinien, die maximale Anzahl von Verbindungen zu einem Host, Ressourcen- und Netzwerk-Timeouts usw. festlegt. Dies ist eine wesentliche Verbesserung gegenüber NSURLConnection, die auf ein globales Konfigurationsobjekt mit viel weniger Flexibilität angewiesen war.

Wandlungsfähigkeit

Sobald eine Sitzung erstellt und konfiguriert wurde von NSURLSessionConfiguration In diesem Fall kann die Konfiguration der Sitzung nicht geändert werden. Wenn Sie die Konfiguration einer Sitzung ändern müssen, müssen Sie eine neue Sitzung erstellen. Beachten Sie, dass Sie die Konfiguration einer Sitzung kopieren und ändern können. Die Änderungen haben jedoch keine Auswirkungen auf die Sitzung, aus der die Konfiguration kopiert wurde.

Standardkonfiguration

Das NSURLSessionConfiguration class bietet drei Factory-Konstruktoren zum Instantiieren von Standardkonfigurationen, defaultSessionConfiguration, ephemeralSessionConfiguration, und backgroundSessionConfiguration. Die erste Methode gibt eine Kopie von zurück Standardkonfiguration der Sitzung Objekt, das zu einer Sitzung führt, die sich ähnlich wie eine NSURLConnection Objekt in seiner Standardkonfiguration. Ändern einer Sitzungskonfiguration über defaultSessionConfiguration Die Factory-Methode ändert die Standardsitzungskonfiguration, von der sie eine Kopie ist, nicht.

Ephemere Konfiguration

Ein Sitzungskonfigurationsobjekt, das durch Aufrufen von erstellt wurde ephemeralSessionConfiguration Die Factory-Methode stellt sicher, dass die resultierende Sitzung keinen permanenten Speicher für Cookies, Caches oder Anmeldeinformationen verwendet. Mit anderen Worten, Cookies, Caches und Anmeldeinformationen werden gespeichert. Ephemere Sitzungen sind daher ideal, wenn Sie privates Browsing implementieren müssen, was vor der Einführung von nicht möglich war NSURLSession.

Hintergrundkonfiguration

Das backgroundSessionConfiguration: Die Factory-Methode erstellt ein Sitzungskonfigurationsobjekt, das das Hochladen und Herunterladen außerhalb des Prozesses ermöglicht. Die Upload- und Download-Tasks werden von einem Hintergrund-Daemon verwaltet und laufen auch dann weiter, wenn die Anwendung angehalten wird oder abstürzt. Wir werden später in dieser Serie mehr über Hintergrundsitzungen sprechen.

Sitzungskonfiguration

Wie wir im vorherigen Tutorial gesehen haben, ist das Erstellen eines Sitzungskonfigurationsobjekts einfach. In dem unten gezeigten Beispiel habe ich die verwendet defaultSessionConfiguration Fabrikmethode zum Erstellen eines NSURLSessionConfiguration Beispiel. Zum Konfigurieren eines Sitzungskonfigurationsobjekts müssen Sie nur die Eigenschaften ändern, wie im Beispiel gezeigt. Wir können dann das Sitzungskonfigurationsobjekt verwenden, um ein Sitzungsobjekt zu instanziieren. Das Sitzungsobjekt dient als Factory für Daten-, Upload- und Download-Aufgaben, wobei jede Aufgabe einer einzelnen Anforderung entspricht. Im folgenden Beispiel wird die iTunes-Such-API wie im vorherigen Lernprogramm abgefragt.

 // Sitzungskonfiguration erstellen NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; // Sitzungskonfiguration konfigurieren [sessionConfiguration setAllowsCellularAccess: YES]; [sessionConfiguration setHTTPAdditionalHeaders: @ @ "Accept": @ "application / json"]; // Session erstellen NSURLSession * session = [NSURLSession sessionWithConfiguration: sessionConfiguration]; // Send Request NSURL * url = [NSURL URLWithString: @ "https://itunes.apple.com/search?term=apple&media=software"]; [[session dataTaskWithURL: URL completionHandler: ^ (NSData * -Daten, NSURLResponse * -Antwort, NSError * -Fehler) NSLog (@ "% @", [NSJSONSerialization JSONObjectWithData: Datenoptionen: 0 Fehler: nil]); ] fortsetzen];

Das Beispiel zeigt auch, wie einfach das Hinzufügen von benutzerdefinierten Kopfzeilen ist HTTPAdditionalHeaders Eigenschaft des Sitzungskonfigurationsobjekts. Die Schönheit der NSURLSession API ist, dass jede Anforderung, die die Sitzung durchläuft, durch das Konfigurationsobjekt der Sitzung konfiguriert wird. Das Hinzufügen von Authentifizierungs-Headern zu einem Satz von Anforderungen ist zum Beispiel ein Kinderspiel.


Downloads abbrechen und fortsetzen

In der vorherigen Anleitung habe ich Ihnen gezeigt, wie Sie ein Bild mithilfe von herunterladen NSURLSession API. Netzwerkverbindungen sind jedoch unzuverlässig und es kommt zu oft vor, dass ein Download aufgrund einer unübersichtlichen Netzwerkverbindung fehlschlägt. Glücklicherweise ist es nicht schwierig, einen Download fortzusetzen NSURLSession API. Im nächsten Beispiel zeige ich Ihnen, wie Sie den Download eines Bildes abbrechen und fortsetzen können.

Bevor wir uns mit der Wiederaufnahme einer Download-Aufgabe näher beschäftigen, ist es wichtig, den Unterschied zwischen dem Abbrechen und dem Unterbrechen einer Download-Aufgabe zu verstehen. Es ist möglich, eine Download-Aufgabe anzuhalten und zu einem späteren Zeitpunkt fortzusetzen. Wenn Sie eine Download-Aufgabe abbrechen, wird die Aufgabe jedoch abgebrochen, und es ist nicht möglich, sie später wieder aufzunehmen. Es gibt jedoch eine Alternative. Es ist möglich, eine Download-Aufgabe durch Aufrufen abzubrechen cancelByProducingResumeData: darauf Es akzeptiert einen Beendigungshandler, der einen Parameter akzeptiert NSData Objekt, das verwendet wird, um den Download zu einem späteren Zeitpunkt durch Aufrufen wieder aufzunehmen downloadTaskWithResumeData: oder downloadTaskWithResumeData: completionHandler: auf einem Session-Objekt. Das NSData Das Objekt enthält die erforderlichen Informationen, um die Download-Task dort fortzusetzen, wo sie aufgehört hat.

Schritt 1: Outlets und Aktionen

Öffnen Sie das Projekt, das wir im vorherigen Tutorial erstellt haben, oder laden Sie es hier herunter. Wir fangen damit an, der Benutzeroberfläche zwei Schaltflächen hinzuzufügen, eine zum Abbrechen des Downloads und eine zum Fortsetzen des Downloads. Erstellen Sie in der Header-Datei des View-Controllers einen Auslass und eine Aktion für jede Schaltfläche (siehe unten).

 #einführen  @interface MTViewController: UIViewController @property (schwach, nicht atomar) IBOutlet UIButton * cancelButton; @ property (schwach, nichtatomisch) IBOutlet UIButton * resumeButton; @ property (schwach, nichtatomisch) IBOutlet UIImageView * imageView; @ property (schwach, nicht atomar) IBOutlet UIProgressView * progressView; - (IBAction) cancel: (ID) Absender; - (IBAction) Lebenslauf: (ID) Absender; @Ende

Schritt 2: Benutzeroberfläche

Öffnen Sie das Haupt-Storyboard des Projekts und fügen Sie der Ansichts-Controller-Ansicht zwei Schaltflächen hinzu. Positionieren Sie die Tasten wie in der Abbildung unten gezeigt, und verbinden Sie jede Taste mit der entsprechenden Steckdose und Aktion.


Schritt 3: Umgestaltung

Wir müssen ein wenig umgestalten, damit alles korrekt funktioniert. Öffnen MTViewController.m und deklarieren Sie eine Instanzvariable und zwei Eigenschaften. Die Instanzvariable, Session, enthält einen Verweis auf die Sitzung, die wir zum Herunterladen des Bildes verwenden.

 #import "MTViewController.h" @interface MTViewController ()  NSURLSession * _session;  @ property (strong, nonatomic) NSURLSessionDownloadTask * downloadTask; @ property (strong, nonatomic) NSData * resumeData; @Ende

Wir müssen auch das umgestalten viewDidLoad Methode, aber zuerst möchte ich eine Getter-Methode für die Sitzung implementieren. Die Implementierung ist ziemlich einfach, wie Sie unten sehen können. Wir erstellen ein Sitzungskonfigurationsobjekt mit dem defaultSessionConfiguration Factory-Methode und instanziieren das Sitzungsobjekt damit. Der Ansichtscontroller dient als Delegierter der Sitzung.

 - (NSURLSession *) session if (! _Session) // Sitzungskonfiguration erstellen NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; // Sitzung erstellen _session = [NSURLSession sessionWithConfiguration: sessionConfiguration delegate: self delegateQueue: nil];  return _session; 

Mit dem Session Accessor implementiert, der viewDidLoad Methode wird viel einfacher. Wir erstellen eine Download-Aufgabe wie in der vorherigen Übung und speichern einen Verweis auf die Aufgabe in downloadTask. Wir weisen dann die Download-Aufgabe an fortsetzen.

 - (void) viewDidLoad [super viewDidLoad]; // Create Download Task self.downloadTask = [self.session downloadTaskWithURL: [NSURL URLWithString: @ "http://cdn.tutsplus.com/mobile/uploads/2014/01/5a3f1-sample.jpg"]]; // Download-Task fortsetzen [self.downloadTask-Lebenslauf]; 

Schritt 4: Download abbrechen

Das stornieren: Aktion enthält die Logik zum Abbrechen der gerade erstellten Download-Aufgabe. Ob downloadTask ist nicht Null, wir nennen cancelByProducingResumeData: auf die aufgabe. Diese Methode akzeptiert einen Parameter, einen Beendigungsblock. Der Beendigungsblock benötigt auch einen Parameter, eine Instanz von NSData. Ob resumeData ist nicht Null, Wir speichern einen Verweis auf das Datenobjekt in den View Controller resumeData Eigentum.

Wenn ein Download nicht fortgesetzt werden kann, wird der Abschlussblock gesperrt resumeData Parameter ist Null. Nicht jeder Download ist wiederaufnehmbar, daher ist es wichtig zu prüfen, ob resumeData ist gültig NSData Objekt.

 - (IBAction) cancel: (id) sender if (! Self.downloadTask) zurückkehren; // Hide-Schaltfläche ausblenden [self.cancelButton setHidden: YES]; [self.downloadTask cancelByProducingResumeData: ^ (NSData * resumeData) if (! resumeData) return; [self setResumeData: resumeData]; [self setDownloadTask: nil]; ]; 

Schritt 5: Den Download fortsetzen

Das Wiederaufnehmen der Download-Aufgabe nach dem Abbruch ist einfach. In dem fortsetzen: Aktion prüfen wir, ob der View Controller resumeData Eigenschaft ist gesetzt. Ob resumeData ist gültig NSData Objekt, sagen wir dem Session Objekt anlegen, um eine neue Download-Aufgabe zu erstellen und die zu übergeben NSData Objekt. Das ist alles Session Das Objekt muss die Download-Aufgabe neu erstellen, die wir in der Datenbank abgebrochen haben stornieren: Aktion. Wir weisen dann die Download-Aufgabe an fortsetzen und setzen resumeData zu Null.

 - (IBAction) resume: (id) sender if (! Self.resumeData) zurückkehren; // Hide Resume Button [self.resumeButton setHidden: YES]; // Create Download Task self.downloadTask = [self.session downloadTaskWithResumeData: self.resumeData]; // Download-Task fortsetzen [self.downloadTask-Lebenslauf]; // Bereinigung [self setResumeData: nil]; 

Erstellen Sie das Projekt und führen Sie die Anwendung im iOS-Simulator oder auf einem physischen Gerät aus. Der Download sollte automatisch starten. Tippen Sie auf die Schaltfläche "Abbrechen", um den Download abzubrechen, und tippen Sie auf die Schaltfläche "Resume", um den Download fortzusetzen.

Schritt 6: Fertigstellen von Berührungen

Es gibt eine Reihe von Details, auf die wir achten müssen. Zunächst sollten die Schaltflächen nicht immer sichtbar sein. Wir verwenden die Schlüsselwertbeobachtung, um die Schaltflächen bei Bedarf ein- und auszublenden. Im viewDidLoad, Blenden Sie die Schaltflächen aus und fügen Sie den View Controller als Beobachter für sich hinzu resumeData und downloadTask Schlüsselpfade.

 - (void) viewDidLoad [super viewDidLoad]; // Observer hinzufügen [self addObserver: self forKeyPath: @ "resumeData" -Optionen: NSKeyValueObservingOptionNew context: NULL]; [self addObserver: self forKeyPath: @ "downloadTask" -Optionen: NSKeyValueObservingOption Neuer Kontext: NULL]; // Benutzeroberfläche einrichten [self.cancelButton setHidden: YES]; [self.resumeButton setHidden: YES]; // Create Download Task self.downloadTask = [self.session downloadTaskWithURL: [NSURL URLWithString: @ "http://cdn.tutsplus.com/mobile/uploads/2014/01/5a3f1-sample.jpg"]]; // Download-Task fortsetzen [self.downloadTask-Lebenslauf]; 

Im observValueForKeyPath: ofObject: change: context:, Wenn nicht, wird der Abbrechen-Button ausgeblendet resumeData ist Null und wir verstecken den Resume-Button, wenn downloadTask ist Null. Erstellen Sie das Projekt und führen Sie die Anwendung noch einmal aus, um das Ergebnis anzuzeigen. Das ist besser. Recht?

 - (void) observValueForKeyPath: (NSString *) keyPath ofObject: (id) Objektänderung: (NSDictionary *) Kontext ändern: (void *) Kontext if ([keyPath isEqualToString: @ "resumeData"]) ^ [self.resumeButton setHidden: (self.resumeData == nil)];);  else if ([keyPath isEqualToString: @ "downloadTask"]) dispatch_async (dispatch_get_main_queue (), ^ [self.cancelButton setHidden: (self.downloadTask == nil)];); 
Wie George Yang in den Kommentaren betont, wissen wir nicht, ob observValueForKeyPath: ofObject: change: context: wird im Hauptthread aufgerufen. Es ist daher wichtig, die Benutzeroberfläche in einem GCD-Block (Grand Central Dispatch) zu aktualisieren, der in der Hauptwarteschlange aufgerufen wird.

Schritt 7: Die Sitzung wird ungültig gemacht

Es gibt einen wichtigen Aspekt von NSURLSession über die ich noch nicht gesprochen habe, Sitzungsunfähigkeit. Die Sitzung enthält einen starken Verweis auf ihren Delegierten, was bedeutet, dass der Delegierte nicht freigegeben wird, solange die Sitzung aktiv ist. Um diesen Referenzzyklus zu unterbrechen, muss die Sitzung ungültig gemacht werden. Wenn eine Sitzung ungültig gemacht wird, werden aktive Aufgaben abgebrochen oder abgeschlossen, und der Delegat wird gesendet URLSession: didBecomeInvalidWithError: Nachricht und die Sitzung gibt ihren Delegierten frei.

Es gibt mehrere Orte, an denen wir die Sitzung ungültig machen können. Da der View Controller nur ein Bild herunterlädt, kann die Sitzung nach Abschluss des Downloads für ungültig erklärt werden. Schauen Sie sich die aktualisierte Implementierung von an URLSession: downloadTask: didFinishDownloadingToURL:. Die Abbrechen-Schaltfläche wird auch ausgeblendet, wenn der Download abgeschlossen ist.

 - (void) URLSession: (NSURLSession *) Sitzung downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) location NSData * data = [NSData dataWithContentsOfURL: location]; dispatch_async (dispatch_get_main_queue (), ^ [self.cancelButton setHidden: YES]; [self.progressView setHidden: YES]; [self.imageView setImage: [UIImage imageWithData: data]];); // Sitzung ungültig machen [session finishTasksAndInvalidate]; 

Fazit

Das Beispielprojekt, das wir in diesem Lernprogramm erstellt haben, ist eine vereinfachte Implementierung zum Abbrechen und Fortsetzen von Downloads. In Ihren Anwendungen muss möglicherweise das geschrieben werden resumeData Objekt für spätere Verwendung auf Platte speichern, und es ist möglich, dass mehrere Download-Tasks gleichzeitig ausgeführt werden. Obwohl dies die Komplexität erhöht, bleiben die Grundprinzipien gleich. Stellen Sie sicher, dass Speicherverluste vermieden werden, indem Sie eine Sitzung, die Sie nicht mehr benötigen, immer für ungültig erklären.