SwiftUI: Erstellen eines eigenen Edit-Buttons

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


Kommentare

10 Antworten zu „SwiftUI: Erstellen eines eigenen Edit-Buttons“

  1. 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

    1. 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.

    2. Avatar von Christoph
      Christoph

      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)

      1. Avatar von Christoph
        Christoph

        sorry das war unvollständig, sollte heissen:

        var editMode: Binding?

        1. Hi Christoph, vielen Dank für deinen Kommentar und dein Feedback bezüglich Jans Frage. 🙂

  2. 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.

    1. 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.

  3. 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

  4. Hi Thomas, sehr hilfreich und verständlich erklärt. Nettes kleines Feature!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert