Warum die Reihenfolge von Modifier-Aufrufen so wichtig ist
Mithilfe der Modifier konfiguriert man das Aussehen und Verhalten von Views in SwiftUI. Das Vorgehen dieser speziellen Methoden ist hierbei besonders interessant. Sie nehmen die View, auf der sie aufgerufen werden, als Basis und verändern sie dem Verhalten des jeweiligen Modifiers entsprechend (setzen so beispielsweise eine Farbe für einen Text oder Verändern die Größe der View). Im Anschluss liefern sie eine gänzlich neue View zurück, die auf der ursprünglichen View basiert und zusätzlich die vom Modifier durchgeführten Änderungen enthält. Die folgende Grafik skizziert dieses Verhalten beispielhaft.
Durch die Aneinanderreihung von Modifiern entsteht so eine Kette, in der ein Modifier die jeweils vorangegangene View manipuliert und als Ergebnis eine neue View zurück liefert.
Doch genau aufgrund dieses Verhaltens muss man bisweilen bezüglich der Reihenfolge der Modifier-Aufrufe Vorsicht walten lassen. Demonstrieren möchte ich das an einem Beispiel. In dem folgenden Listing werden zwei Views erstellt, die generell identisch sind. Es handelt sich jeweils um eine Text
-Instanz, die mittels der Modifier padding()
und border(_:width:)
konfiguriert werden. Der einzige Unterschied der beiden Views besteht in der Reihenfolge, in der die Aufrufe der genannten Modifier erfolgen.
struct FirstTextView: View {
var body: some View {
Text("Hello, World!")
.padding()
.border(Color.gray, width: 1)
}
}
struct SecondTextView: View {
var body: some View {
Text("Hello, World!")
.border(Color.gray, width: 1)
.padding()
}
}
Dieser kleine Unterschied hat große Auswirkungen, wie das folgende Bild deutlich macht. Beide Views werden unterschiedlich dargestellt.
Genau das hängt mit der Reihenfolge und somit der Abarbeitung der Modifier zusammen. Werfen wir dazu einmal einen genaueren Blick auf den Code.
FirstTextView
wird zunächst um Abstände zu allen Seiten mittels des padding()
-Modifiers ergänzt. padding()
generiert entsprechend eine neue View auf Basis von Text("Hello, World!")
, fügt der zusätzliche Abstände hinzu und liefert das Ergebnis zurück. Jene neue View – also die, die um die Abstände ergänzt wurde – erhält dann mittels border(_:width:)
-Modifier noch einen Rahmen.
Bei SecondTextView
hingegen wird zuerst der Rahmen mittels Aufruf von border(_:width:)
gesetzt. Da die Text
-View zu diesem Zeitpunkt keinerlei Abstände besitzt, legt sich der Rahmen direkt um den anzuzeigenden Text. Erst danach folgt der Aufruf des padding()
-Modifiers auf diese neue View. So werden zwar am Ende auch SecondTextView
passende Abstände zu allen Seiten hinzugefügt. Die wirken sich nur nicht auf den Rahmen aus, da der um den Text gelegt wurde, bevor der Text selbst über irgendwelche Abstände verfügte.
Prinzipiell können durchaus beide Varianten korrekt sein. Das hängt letztlich davon ab, welches Ziel man erreichen möchte und wie die View aussehen und sich verhalten soll. Beispielsweise ließe sich nun im Falle von SecondTextView
nach dem Aufruf von padding()
ein zweiter Rahmen ergänzen, der sich um die Abstände legt:
struct SecondTextView: View {
var body: some View {
Text("Hello, World!")
.border(Color.gray, width: 1)
.padding()
.border(Color.black, width: 3)
}
}
Fazit
Das Prinzip, Views mittels Modifier zu konfigurieren und als Ergebnis jeweils eine komplett neue View zurück zu liefern, ist durchaus spannend. Es funktioniert auch einwandfrei, sofern man sich bewusst macht, dass aufgrund dieser Funktionsweise die Reihenfolge der Modifier-Aufrufe in bestimmten Fällen eine wichtige Rolle spielt. Auch wenn das umgekehrt nicht immer der Fall ist. So könnt ihr einen Text zuerst fett formatieren und anschließend rot einfärben; oder eben genau umgekehrt vorgehen. In beiden Fällen ist das Ergebnis dasselbe.
Wie ihr aber an dem gezeigten Beispiel sehr schön gesehen habt, führt die Reihenfolge der Modifier-Aufrufe in bestimmten Szenarien zu gänzlich unterschiedlichen Ergebnissen. Hat man diese Problematik und so die Funktionsweise der Modifier aber erst einmal verinnerlicht, fällt die Arbeit mit ihnen gleich deutlich leichter (und es kommt nicht zu überraschenden und unerwarteten Ergebnissen).
Euer Thomas
Schreibe einen Kommentar