swift optional unwrapping

Die Optionals in Swift sind für Einsteiger eine Herausforderung. Denn jeder Datentyp kann unter Swift ein Optional sein. Entweder enthält die Variable Daten vom jeweiligen Typ oder nil. Da also vielleicht keine Daten vorliegen, muss dieser Fall eingeplant werden. Dieser Ratgeber zeigt Dir die wichtigsten Grundlagen.

 

Optional Grundlagen

Warum Optionals?

Das eine Variable manchmal keinen Wert enthält, wird über Optionals bereits in der Syntax signalisiert. Während auch in anderen Sprachen solche Situationen nicht unüblich sind, wird die Behandlung dieser Situationen nicht erzwungen. In Swift wird dank der Optionals eine bewusste Entscheidung zur Verarbeitung gefordert.

Optionals definieren

In aller Kürze noch einmal die Wiederholung der Basics. Ein Optional wird mit der Fragezeichen hinter dem Datentyp deklariert:

Zunächst gibt es hier keinen Wert bzw. nil. Im weiteren Programmverlauf kann nun ein Wert gesetzt werden. Oder ein vorhandener Wert auch wieder mit nil überschrieben werden.

Zugriff auf Optionals

Besonders ist nun, dass ein Optional nicht einfach weiterverwendet werden kann. Gedanklich ist der Optional ein Container, in dem ggf. ein Wert beliebigen Typs verpackt wurde:

Hier wird nicht (nur) der String „Datei nicht gefunden“ ausgegeben. Gleichzeitig wird der Hinweis auf den Optional deutlich:

Optional(„Datei nicht gefunden“)

Der Zugriff auf den Wert wird als Optional Unwrapping bezeichnet. Der eigentliche Inhalt wird sozusagen wieder ausgepackt. Und da es viele Wege dafür gibt, ist dieses Thema für Einsteiger nicht unbedingt übersichtlich. Dieser Ratgeber räumt damit auf.

Forced Unwrapping

Das erzwungene Auspacken ist der erste Schritt. Es wird als forced unwrapping bezeichnet. Diese Techniken sind potenziell gefährlich, da sie möglicherweise zu schweren Fehlern führen. Trotzdem sind sie für das grundlegende Verständnis wichtig.

Forced Unwrapping – eine mögliche Fehlerquelle

Über das Ausrufezeichen (sinngemäß das Gegenteil vom Fragezeichen) hinter einem Optional wird das Unwrapping erzwungen:

Warnung: Das funktioniert fehlerfrei wenn ein Wert vorhanden ist. Steht in der Variable nil, führt das zu einem schweren Ausnahmefehler. Deswegen darf dieser Code so nicht verwendet werden. Wichtig ist zumindest die vorherige Prüfung auf nil.

Besser: Prüfung auf nil

Im Beispiel oben wird versucht die Fehlermeldung auszugeben. Das Unwrapping wird aber forciert, was ein Problem verursacht wenn einfach keine Meldung gesetzt wurde. Die Mindestanforderung ist also zu prüfen ob die Variable ggf. nil enthält:

Das Unwrapping findet nur noch statt, wenn nicht in der Variable nicht nil steht. Das behebt den Fehler, ist aber nicht unbedingt die beste Lösung. Immerhin findet eine Prüfung statt. Gleichzeitig muss aber der Optional erneut behandelt werden. Das kann einfacher gelöst werden.

Implicit Unwrapping?

Das implizite Unwrapping ist eine (gefährliche) Vereinfachung der obigen Techniken. Auch hier wird ein Optional deklariert, allerdings mit Ausrufezeichen statt Fragezeichen. Beim Zugriff wird nun mit Forced Unwrapping gearbeitet, mit allen Konsequenzen:

Ist der Wert in der Variable fehlermeldung nil, gibt es einen schweren Fehler. Es verstößt in gewisser Hinsicht auch gegen die neuen API Design Guidelines. Ein zentraler Aspekt ist clarity at the point of use (Klarheit zum Zeitpunkt der Verwendung). Das ist nicht gegeben. Der Optional ist nicht erkennbar, wenn die Deklaration ggf. weiter entfernt stattfindet.

Wichtig: Die Nutzung von Implicit Unwrapping sollte nicht die erste Wahl sein. Es gibt nämlich noch bessere Techniken, die einen sauberen Umgang mit Optionals ermöglichen.

 

eBook: Swift Optional Unwrapping


cover

Bonus: Lieber später (noch einmal) lesen? Jetzt HIER KLICKEN und das kostenlose eBook herunterladen!

Clean Unwrapping

Optional Binding mit if let / if var

Das Optional Binding ist eine Kombination aus if-Bedingung und Zuweisung zu einer temporären Konstante. Die Konstante code ist nur innerhalb der if-Bedingung gültig:

Ein Nachteil des Bindings: Wenn wie im Beispiel der Optional im gleichen Gültigkeitsbereich definiert wird, muss die temporäre Konstante oder Variable einen anderen Namen erhalten. Die neue Konstante dürfte nicht ebenfalls fehlerCode heißen.

Das sieht anders aus, wenn ein Parameter ausgepackt werden soll, oder die Eigenschaft einer Klasse:

In beiden Fällen wird der Optional temporär überschrieben.

Fun fact: Es könnte ebenso mit var eine Variable deklariert werden:

In der Praxis habe ich das bisher aber nur selten gesehen und auch bisher noch nicht verwendet.

Binding über „guard let“

Ein Problem des Optional Bindings über if-Bedingungen ist die Verschachtelung. Der Zugriff auf die Konstante ist nur innerhalb der Bedingung möglich. Die abhängige Logik muss verschachtelt werden.

Optional Unwrapping über guard funktioniert ähnlich. Das speziell für Methoden und Funktionen gedachte Konstrukt ermöglicht im Fehlerfall den vorzeitigen Ausstieg. Wenn ein Wert vorhanden war, ist die erzeugte Konstante anschließend im Namensraum verfügbar:

Das Beispiel von oben ist hier noch einmal mit guard zu sehen. Hier wird nur die print()-Funktion aufgerufen. Sobald mehrere Anweisungen ausgeführt werden, ist die fehlende Verschachtelung schnell sehr angenehm.

Optional Chaining

Das Optional Chaining ist eine weitere Technik für Dein Optional-Kungfoo. Zuerst ein Beispiel:

Deine Aufgabe: Du musst den Namen der Person in der Funktion vornameVon(teilnehmer:) ausgeben. Im Weg stehen Dir zwei Optionals. Sowohl die Variable person als auch der Vorname im Objekt könnten nil enthalten.

Lösung #1:

Hier werden die Optionals nacheinander bearbeitet. Das Optional Chaining ist kürzer, bewirkt aber das gleiche.

Lösung #2 (mit Optional Chaining):

Nun bleibt person ein Optional. Die Verkettung wird über das Fragezeichen eingeleitet. Vor dem Zugriff wird die Variable geprüft. Ist person bereits nil, wird nil zurückgegeben. Wenn ein Wert in person enthalten ist, wird vorname geprüft und ggf. der Inhalt zurückgegeben.

nil-coalescing Operator (??)

Ein wichtiges Tool im Umgang mit Optionals gibt es noch: den nil-coalescing Operator. Der Name ist viel abschreckender als der Einsatzzweck. Ein Beispiel.

Die Hintergrundfarbe soll bestimmt werden. Entweder wählt der Benutzer einen Wert, oder ein Standardwert wird übernommen (in diesem Fall „weiß“):

Über die Kurzform von if geht das etwas kürzer:

Nachteil: Der Optional wird mehrfach genannt, erst in der Bedingung und dann noch einmal explizit beim Forced Unwrapping. Der nil-coalescing Operator (??) macht das gleiche, aber schöner:

Wenn userColor einen Wert enthält, wird der genutzt. Ansonsten wird der hintergrundFarbe der Wert weiß zugewiesen.

eBook: Swift Optional Unwrapping


cover

Bonus: Lieber später (noch einmal) lesen? Jetzt HIER KLICKEN und das kostenlose eBook herunterladen!

Fazit

Es gibt einige Techniken für den Umgang mit Optionals. Mittlerweile ist das guard-Statement mein absoluter Favorit. Außerdem von Funktionen und Methoden nutze ich if/let. Das Forced Unwrapping nutze ich wirklich nur, wenn nil als Wert ausgeschlossen wurde. Das Implicit Unwrapping ist eher eine Technologie, die für den Übergang von Objective-C sinnvoll ist. In eigenem Swift-Code versuche ich darauf zu verzichten.

Was sind Deine Erfahrungen mit Optionals? Findest Du den Artikel hilfreich? Hast Du noch Fragen? Ich freue mich über jegliches Feedback!

Kommentare (4)

  • Uwe

    1 Jahr ago

    Vielen, vielen dank für diese gute Zusammenfassung des Themas Optionals. Mein Favorit ist der nil-coalescing Operator ??.
    Genau so Nagel auf den Kopf getroffen wie ++i. (Hoffe bleibt uns erhalten, könnte ja jemanden irritieren:)

    • Jan Brinkmann

      1 Jahr ago

      Herzlich gern! Ich denke der Coalescing Operator bleibt uns erhalten, der wurde erst nachträglich eingeführt 🙂

  • Daniel Bocksteger

    11 Monaten ago

    Super eBook und perfekt dazu passender Beitrag! Hab mir das eBook direkt ausgedruckt und abgeheftet im Büro 🙂 Danke für die tollen Erklärungen und das Herausstellen von Vor- bzw. Nachteilen der einzelnen Verfahren 🙂

Schreib einen Kommentar

Your email address will not be published.