SwiftUI in der Praxis, Teil 1

Seite 2: Notizen erstellen

Inhaltsverzeichnis

Über ContentView lassen sich nun zwar Notizen darstellen, doch noch fehlt eine Funktion, um überhaupt neue Notizen erzeugen zu können. Hierfür fügen Entwickler dem Xcode-Projekt eine neue SwiftUI-View über die entsprechende Vorlage hinzu (s. Abb. 2) und geben ihr den Namen NoteView. Sie soll gleichermaßen zum Erstellen neuer wie auch zur späteren Bearbeitung bestehender Notizen dienen. Deshalb erhält die View direkt eine Property namens note, über die ihr die zu bearbeitende Note-Instanz übergeben wird.

Neue Views lassen sich in Xcode über die Vorlage SwiftUI View einem Projekt hinzufügen (Abb. 2).

Generell wird die Implementierung dieser Property aber nun ein wenig komplexer. Schließlich soll NoteView nicht nur Informationen zu einer Notiz anzeigen, sondern sie auch ändern. Um das zu ermöglichen, ist die note-Property mit dem Property Wrapper @ObservedObject zu deklarieren. Das wiederum ist aber nur möglich, wenn die zugehörige Klasse (hier also Note) konform zum ObservableObject-Protokoll ist.

Das Protokoll ermöglicht es, SwiftUI-Views über Änderungen in bestimmten Properties zu informieren. Kommt es sodann zu einer solchen Änderung, werden die zugehörigen Views automatisch aktualisiert. Um solche Updates zu erhalten, sind die entsprechenden Properties mit dem @Published-Property-Wrapper zu deklarieren. Im Zuge der Aktualisierung der Note-Klasse nutzt man das direkt aus und versieht die drei Properties title, content und isFavorite damit. Wenn sich nun diese Eigenschaften einer Notiz ändern, werden alle zugehörigen Views automatisch entsprechend aktualisiert. Die nun erneut überarbeitete Variante der Note-Klasse zeigt Listing 5:

// Listing 5: Umsetzung der Note-Klasse als ObservableObject
class Note: Identifiable, ObservableObject {
    var id = UUID()
    @Published var title: String
    @Published var content: String
    @Published var isFavorite: Bool
    
    init(title: String = "", content: String = "", isFavorite: Bool = false) {
        self.title = title
        self.content = content
        self.isFavorite = isFavorite
    }
}

Nun wieder zurück zur NoteView. Ihre Basis ist ein VStack, der ein Textfeld zum Ändern des Titels und eine Text-View zur Bearbeitung des Inhalts enthält. Das Textfeld lässt sich über eine Instanz der Structure TextField umsetzen. Sie erwartet bei der Initialisierung zwei Parameter: einen Platzhalter-Text (im Beispiel "Title") und ein Binding zu jenem String, der angezeigt und möglicherweise geändert werden soll. Hierfür dient die title-Property der der View übergebenen Notiz. Auf die greift man über eine passende note-Property zu, die mit @ObservedObject deklariert ist. Sie erfordert es jedoch, eine passende Note-Instanz bei Initialisierung der NoteView zu übergeben. Das führt dazu, dass der Preview-Provider zwingend anzupassen ist, andernfalls kommt es zu einem Compiler-Fehler. Hier reicht es aber aus, eine einfache Dummy-Instanz für Preview-Zwecke zu verwenden. Den bisherigen Code für die NoteView-Structure zeigt Listing 6:

// Listing 6: Erste Version der NoteView-Structure (inklusive angepasstem Preview-Provider)
struct NoteView: View {
    @ObservedObject var note: Note
    
    var body: some View {
        VStack {
            TextField("Title", text: $note.title)
            // TODO: Implement text-view.
        }
    }
}

struct NoteView_Previews: PreviewProvider {
    static var previews: some View {
        NoteView(note: Note(title: "Lorem ipsum", content: "Lorem ipsum ..."))
    }
}