Im Zuge meiner aktuellen Let’s Code-Reihe auf YouTube entwickelte ich vor kurzem einen eigenen Edit-Button in SwiftUI. Dieser Button hat eine vergleichbare Aufgabe wie die View EditButton
aus dem SwiftUI-Framework. Allerdings ist EditButton
nicht sonderlich flexibel. Möchte ich beispielsweise einen alternativen Text oder gar Grafiken für den Button verwenden, muss man zu einer eigens kreierten Lösung greifen.
Wie auch ihr eure eigenen Edit-Buttons in SwiftUI erstellen könnt, erläutere ich im Folgenden.
Die Basis: das Environment
Mit die wichtigste Rolle bei einem eigenen Edit-Button auf Basis von SwiftUI spielt das Environment, genauer gesagt der Wert für den Key-Path editMode
. Der liefert uns in Form eines Bindings Zugriff auf eine Instanz vom Typ EditMode
. Und diese Instanz ist entscheidend! Sie informiert uns einerseits darüber, ob gerade der Edit-Mode einer View aktiv ist oder nicht. Diese Information können wir über die boolesche Property isEditing
von EditMode
auslesen.
Zum anderen nutzen wir diese EditMode
-Instanz, um aktiv und programmatisch eine Änderung des Edit-Modes herbei zu führen. Schließlich soll unser eigener Edit-Button den Edit-Mode ja auch sowohl aktivieren als auch deaktivieren können.
Das Binding, das man über das Environment und den Schlüssel editMode
erhält, ist ein Optional. Um darauf zugreifen zu können, muss man es also entpacken.
Im folgenden Listing seht ihr einmal, wie sich anhand der genannten Informationen ein eigener Edit-Button auf Basis von SwiftUI umsetzen lässt. Die Hilfs-Property isEditing
dient dazu, auszulesen, ob aktuell der Edit-Mode aktiv ist oder nicht. Diese Information nutze ich bei der Gestaltung des Buttons, um abhängig davon eine andere SF-Symbols Grafik darzustellen; pencil.circle.fill
für einen aktiven Edit-Mode, pencil.circle
für einen inaktiven.
Bei Betätigung des Buttons invertiere ich den momentanen Zustand des Edit-Mode und weise ihn den Wert des Environment-Bindings zu.
struct CustomEditButton: View {
@Environment(\.editMode) var editMode
private var isEditing: Bool {
editMode?.wrappedValue.isEditing ?? false
}
var body: some View {
Button(action: {
withAnimation {
editMode?.wrappedValue = isEditing ? .inactive : .active
}
}, label: {
Image(systemName: isEditing ? "pencil.circle.fill" : "pencil.circle")
.resizable()
.scaledToFit()
.frame(height: 24)
})
}
}
Fazit
Einen eigenen Edit-Button auf Basis von SwiftUI zu erstellen ist erfreulich simpel. Am wichtigsten ist der Zugriff auf das Environment, um in Erfahrung zu bringen, ob der Edit-Mode gerade aktiv ist oder nicht. Außerdem nutzt man das Environment, um den Status des Edit-Mode programmatisch zu überschreiben und ihn so selbst zu aktiveren beziehungsweise zu deaktivieren.
Euer Thomas
Hi Thomas, ich bastel hier an einer App herum, würde auch gerne mal in einer separaten Kontaktaufnahme mit dir quatschen.
Dein Video war wieder sehr klasse und zielgenau erstellt. Genau diesen Anwendungsfall hatte ich gesucht.
Jetzt mal eine Frage.
Warum funktioniert der EditMode für ein View aber dann wenn dieses View in einem anderen View eingebunden wird nicht mehr? Da kommt null Reaktion.
Kannst du hier auch eine Antwort zu geben?
Gruß
Jan
Hi Jan und vielen Dank für dein Feedback! Deine Frage kann ich so aus dem Stand leider nicht beantworten, prinzipiell sollte sich der Edit-Mode aus jeder View heraus abrufen und gegebenenfalls ändern lassen. Da müsste ich einmal einen Blick auf ein konkretes Code-Beispiel werfen, kann aber nicht versprechen, dass ich momentan die Zeit dafür finde, mir das in Ruhe einmal anzusehen.
diese Lösung hat mir gerade auch geholfen, danke sehr an Thomas!
Und ich denke ich kann Jans Frage beantworten:
Es sieht so aus als hätte Jede view ein eigenes Editmode Environment,
wenn du also aus der Subview den Hauptview-Editmode ändern willst (weil da z.B die List ist) musst du deren EditMode als Binding runterreichen:
struct CustomEditButton: View {
var editMode: Binding?
…
(weiter wie gehabt)
sorry das war unvollständig, sollte heissen:
var editMode: Binding?
Hi Christoph, vielen Dank für deinen Kommentar und dein Feedback bezüglich Jans Frage. 🙂
Danke für den Artikel.
Leider ist der „Nachbau“ nicht 100%-ig kompatibel mit dem eingebauten `EditButton`, der seinen Text auch (kurzzeitig) ändert, während man die Swipe-to-delete-Action ausführt.
Das kann sein, diesbezüglich habe ich die eigene Implementierung nicht überprüft. Womöglich gibt es hier noch weitere Status, die man überprüfen kann, oder List/Form besitzt im Zusammenspiel mit Swipe-to-delete noch eine tiefergehende Integration.
after press button and move row to another position function is .inactive and icon is still the same as like .active, then need to press two times to .active
Hi Thomas, sehr hilfreich und verständlich erklärt. Nettes kleines Feature!
Vielen Dank! 😊