unwind-segues

Die Unwind Segues ermöglichen Dir seit iOS6 Dich rückwärts im Navigation Stack zu bewegen. Sie sind gewisser Maßen das Gegenstück zum Segue, der es ermöglicht neue Views anzuzeigen. Im übertragenden Sinn navigierst Du dabei vorwärts. Der Unwind Segue ermöglicht den zurückgelegten “Weg” in die andere Richtung zu gehen. Wenn Du mit Storyboards arbeitest, sind sie ein wichtiges Werkzeug in Deiner Trickkiste. Und deshalb geht es in diesem Artikel um genau dieses Feature.

Unwind Segues in Storyboards

Ein Bild sagt mehr als tausend Worte. Schau Dir folgende Grafik an. Angedeutet wird hier eine App für Online-Shops. Auf dem ersten Screen (1) findest Du die gelb hinterlegten Kategorien. Wird eine Kategorie gewählt, gelangst Du per Segue zum zweiten Screen (2). Dort werden Produkte der Kategorie als graue Kachel angedeutet. Wenn ein Produkt gewählt wird, öffnet sich die Detailansicht in der dritten View (3):

Das Unwind Segue Konzept

Mindestens auf dem dritten Screen möchtest Du nun per Button zur Kategorie bzw. zum Startbildschirm springen. Wie löst Du die Anforderung? Über weitere Verbindungen, die Du umgekehrt anlegst? Achtung: Denn das ist gefährlich und kann schnell zu einem Memory Leak führen. Außerdem erzeugst Du overhead. Es geht einfacher, eben mit genau diesem Sprung rückwärts. Und der wird über Unwind Segues realisiert. Im Navigation Stack gehst Du einfach einen oder mehrere Schritte zurück.

Das Unwind Segues mit Swift

Für die Implementierung von Unwind Segues habe ich ein Startprojekt vorbereitet. Das Ausgangsprojekt kannst Du hier herunterladen. Es handelt sich um eine einfache App, die den Einkauf verschiedener Videotrainings simuliert. Der MenuController stellt in einer Table View mehrere Kurse zu Auswahl:

Simulator Screen Shot 05 Feb 2016 08.01.16

Wird ein Kurs gewählt, kannst Du ihn auf der Detailansicht “buchen”. Hier ist die Klasse DetailController federführend:

unwind-segue-destination

Der Einkauf wird bestätigt und anschließend der ViewController mit der Detailansicht wieder geschlossen werden. Anders ausgedrückt, soll der vorherige Bildschirm wieder angezeigt werden. Du kehrst also zur Liste der Videotrainings zurück. Und genau das realisierst Du nun über den Unwind Segue.

Die Callback Methode anlegen

Um den Unwind Segue anzulegen, muss eine Callback-Methode erzeugt werden. Sie wird in dem Controller hinterlegt, zu dem zurückgesprungen wird und aufgerufen, wenn Du der Segue auslöst. Es handelt sich um eine Action (IBAction). Für den Moment wird keine Logik benötigt, nur die Methode.

Die Methode kannst Du theoretisch frei benennen. Zum Beispiel prepareForUnwind wäre ein guter Kandidat. Wenn aber mehrere Actions, verteilt auf verschiedene Controller vorhanden sind, lohnt es sich das Ziel in den Namen mit aufzunehmen. Den Namen kannst Du dann mit unwindTo einleiten. Eine passende Bezeichnung hier wäre also unwindToMain oder auch unwindToMenu. Da es der Hauptbildschirm ist, habe ich mich für unwindToMain entschieden.

Übergeben wird der Methode nur ein Parameter – das Segue-Objekt selbst. Darauf greifst Du später noch zurück, um Parameter zu übermitteln.

Den Segue anlegen

Vorbereitet wird der Segue nun im Storyboard. Dabei hilft Dir ein Element, dass Du unbewusst sicher schon wahrgenommen hast. Es ist diese kleine Exit-Symbol über dem ViewController:

Screen Shot 2016-02-05 at 08.31.58

Wie bei Erzeugen von anderen Segues musst Du CTRL (oder ggf. STRG) gedrückt halten, klicken und mit der Maus eine Verbindung ziehen. Der Endpunkt ist eben genau dieses Symbol. Im ersten Schritt wirst Du den Segue über den Code auslösen (programmatisch). Dafür muss der Segue im ViewController verfügbar sein. Die Verbindung ziehst Du daher von dem kleinen gelben Symbol zum Exit-Symbol:

unwind-segue-erzeugen

Im Dialogfenster wird Dir anschließend die Methode unwindToMain, die Du einen Schritt vorher angelegt hast, angeboten. Die wählst Du aus. In der Document Outline auf der linken Seite gibt es nun einen neuen Eintrag, wenn alles geklappt hat:

Screen Shot 2016-02-05 at 08.51.50

Das ist schon die halbe Miete. Wenn Du bereits mit Segues gearbeitet hast, weisst Du wie sie ausgelöst werden. Im Code steht Dir die Methode performSegueWithIdentifier zur Verfügung. Was fehlt also noch? Im Namen der Methode ist bereits der Hinweis versteckt! Genau. Ein Identifier. Wähl den Segue aus und gib ihm im Attribute Inspector oben rechts einen Namen:

Screen Shot 2016-02-05 at 09.05.00

Der Identifier ist im Idealfall der Name der Action. Das ist konsistent und außerdem auch sehr übersichtlich. Es wird auf den ersten Blick im Code deutlich, welche Methode aufgerufen wird.

Programmatisch auslösen

Die Vorbereitung ist abgeschlossen. Um in Deiner App rückwärts zu navigieren, muss der Unwind-Prozess auch ausgelöst werden. Im ersten Schritt machst Du das programmatisch, steuerst es also über den Code selbst. Das funktioniert ähnlich wie bei jedem anderen Segue auch.

Die Methode unwindToMain hast Du im MenuController hinterlegt. Das ist Dein Ziel. Ausgelöst wird er am Ausgangspunkt. Und das ist die Detailansicht, also die Klasse DetailController.

Der Workflow der App sieht die Buchung von Kursen vor. Wenn Du die Buchung mit “OK” bestätigst, wird sie (hier bewusst stark vereinfacht) ausgeführt. Im DetailController gibt es die Action kursBuchen. Sie ist mit dem “Jetzt buchen!” Button verknüpft:

Der Benutzer wird über einen UIAlertController zur Bestätigung aufgefordert. Bei der UIAlertAction für “OK” (1) ist bereits ein Handler vorgesehen. Der wird nur dann ausgeführt, wenn der entsprechende Button aktiviert wird. Du löst den Segue also aus, wenn OK gedrückt wird – und zwar an der Stelle, wo jetzt noch das “TODO” als Platzhalter steht.

Der Trigger ist, wie oben beschrieben, die Methode performSegueWithIdentifier. Und die schreibst Du nun an die Stelle des Kommentars mit dem Hinweis “TODO: unwind”:

Herzlichen Glückwunsch, dein erster Unwind Segue ist vollständig. Wenn Du jetzt einen Kurs buchst, springt die App anschließend sauber zum Startbildschirm:

unwind-segue-demo

[plusupgrade]

  • Unwind Segues direkt verknüpfen
  • Parameter über den Segue weiterreichen
  • Videotutorial zu Unwind Segues
  • als PDF herunterladen
  • Quellcode vom fertigen Projekt

[/plusupgrade]

[ds_preview]

Unwind Segues direkt verknüpfen

Es gibt aber noch eine weitere Möglichkeit. Vielleicht möchtest Du in Deiner App einen Button nutzen, um einfach wieder zurückzuspringen. Wenn Du an das Beispiel vom Anfang denkst, sind vielleicht sogar unterschiedliche Ziele denkbar (einmal zur Startbildschirm und einmal zurück in die Kategorieansicht). Du hast nun genug Wissen um eine Action anzulegen und darin den Segue manuell auszulösen. Es geht aber direkter. Getrau dem KISS-Prinzip (halte die Dinge möglichst einfach) reicht es wenn Dein Button direkt mit dem Unwind Segue verknüpft wird.

Ich habe das Beispiel erweitert und einen “Zurück-Button” eingefügt. Einen Button direkt mit dem Sprung zurück zu verbinden, ist denkbar einfach. Dazu nutzt Du auch wieder den CTRL-Button (bzw. STRG) Deiner Tastatur, klickst den Button an und verbindest ihn mit dem kleinen Exit-Symbol oben.

unwind-segue-direkt

Wenn Du die App startest und den Zurück Button aktivierst, wird der Unwind Segue aktiviert und Du gelangst zur Kursauswahl zurück.

Parameter über den Segue weiterreichen

Spannend ist außerdem die Möglichkeit Daten über Unwind Segues zu transportieren. In unserem Beispiel hast Du einen Kurs gebucht. Es wäre ja sinnvoll dies in der Liste auch irgendwie anzudeuten, oder? In anderen Beispielen könntest Du zum Beispiel in einer separaten View eine Farbe auswählen, die in der vorherigen Screen benötigt wird. Es gibt viele Szenarien, in denen ggf. Daten zurückfließen sollen.

Erinnerst Du Dich an die Methode unwindToMain, die Du erstellt hast? Sie wird aufgerufen, wenn der Segue ausgeführt wird. Und genau hier setzt Du nun an. Die schönste Variante wäre ein Parameter für eben genau diese Methode. Das ist allerdings nicht vorgesehen. Leider gibt es auch keine Möglichkeit die Informationen direkt in dem UIStoryboard-Objekt zu übergeben. Das wäre zumindest gefühlt ebenfalls eine saubere Lösung.

In der Praxis funktioniert es wie folgt:

  • am Ausgangspunkt speicherst Du die Werte als Eigenschaft
  • im Parameter segue liest Du die Eigenschaft sourceViewController aus
  • anschließend kannst Du auf die Eigenschaften lesen

Doch bevor Kurse als gebucht markiert werden können, muss das Daten-Model erweitert werden.

Das Model erweitern

Jetzt zeigt sich wie sinnvoll es ist mit einem eigenen Data-Model für Entitäten wie bspw. die Kurse zu arbeiten. Es ist wirklich leicht die bestehende Funktion zu erweitern, ohne an der grundlegenden Struktur etwas zu verändern.

Erweitere die Klasse Kurs um die Eigenschaft gebucht. Da nur ja oder nein in Frage kommen, drängt sich Bool als Datentyp auf. Gleichermaßen muss auch der Initializer (die init-Methode) erweitert werden:

Beim Erzeugen der Objekte bleibt in diesem Beispiel alles wie bisher, da der gerade angelegte Kurs als nicht gebucht markiert wird.

Werte für die Übergabe vorbereiten

Ziel ist herauszufinden ob eine Buchung stattgefunden hat. Dazu nutzen wir die Eigenschaft gebucht vom Typ als boolesche Variable (Bool). Da die Übergabe VOM DetailController ZUM MenuController erfolgt, ist der DetailController der Ausgangspunkt. Hier wird die Eigenschaft benötigt:

Wichtig ist der Anfangswert false. Wir werden in jedem Fall darauf zugreifen. Und solange der Kurs nicht gebucht wurde, ist diese Aussage über die Buchung korrekt.

Vielleicht hast Du es bereits vermutet. Der Wert wird genau dann auf true geändert, wenn die Buchung über den OK-Button bestätigt wurde. Wichtig: das muss vor dem Aufruf von performSegueWithIdentifier geschehen:

Damit steht die Information bereit. Welcher Kurs gebucht wurde, kannst Du ohnehin über die Eigenschaft kurs bestimmen. Dafür ist keine zusätzlich Information notwendig.

Übergebene Daten auslesen

Im Ziel-Controller kannst Du nun in der Action wie folgt die gespeicherten Daten auslesen. Erweitere die Methode unwindToMain in der Klasse MenuController:

Alle Kurse werden aktualisiert und anschließend die Tabelle neu geladen. Damit dort wirklich etwas ändert, fehlt noch ein letzter Schritt.

Gebuchte Kurse mit einem Häkchen markieren

In der Methode tableView(_:cellForRowAtIndexPath) kannst Du die Information gebucht oder nicht gebucht nun verarbeiten. Für jede UITableViewCell kannst Du den sogenannten accessoryType festlegen. In diesem Fall können wir darüber das Häkchen realisieren, indem Du ihn auf das Checkmark setzt:

Videotutorial zu Unwind Segues

Das Videotutorial zu den Unwind Segues findest Du unter folgendem Link:

PDF herunterladen

Der komplette Artikel steht für PLUS-Mitglieder als PDF Dokument zum Download zur Verfügung:

Das finale Projekt herunterladen

Das finale Projekt kannst Du frei verwenden und jeglichen Code als Vorlage für eigene Projekte nutzen. Hier findest Du den Download:

Schreib einen Kommentar

Your email address will not be published.