Hallo! Ich möchte Ihnen etwas über SwiftUI erzählen, ein Framework zum Erstellen von Benutzeroberflächen auf iOS und macOS. Es ist sehr benutzerfreundlich, da es einen deklarativen Programmieransatz verwendet. Mit SwiftUI können Sie beschreiben, wie Ihre Benutzeroberfläche funktionieren und aussehen soll, und das Framework kümmert sich um den Rest.
Eines der Schlüsselelemente von SwiftUI ist die Verwendung von Eigenschaften-Wrappern. Hierbei handelt es sich um Funktionselemente, mit denen Sie zusätzliche Logik für Eigenschaften bereitstellen können.
@Zustand
@Bindung
@ObservedObject
@StateObject
@EnvironmentObject
Sie werden Ihre besten Freunde in der Entwicklung sein.
Mit @State können Sie Eigenschaften erstellen, die geändert werden können, und bei Bedarf die Schnittstelle basierend auf diesen Änderungen aktualisieren. Wenn Sie beispielsweise eine Schaltfläche erstellen möchten, die beim Drücken ihre Farbe ändert, können Sie eine @State-Variable erstellen, um die Farbe zu speichern und sie der Schaltfläche hinzuzufügen:
struct MyButton: View { @State var buttonColor = Color.blue var body: some View { Button("Press me!") { buttonColor = Color.red } .background(buttonColor) } }
Mit @Binding können Sie einen Wert, der in einem Teil des Codes gespeichert ist, in einem anderen Teil des Codes verwenden. In SwiftUI wird es normalerweise verwendet, um einen Wert von einer Ansicht an eine andere zu übergeben, sodass diese miteinander interagieren können. Stellen Sie sich zum Beispiel vor, wir hätten zwei Ansichten – eine mit einem Textfeld und die andere mit einer Schaltfläche. Wir möchten, dass das Textfeld aktualisiert wird, wenn der Benutzer die Schaltfläche drückt. Dazu können wir @Binding verwenden:
struct ContentView: View { @State private var text = "" var body: some View { VStack { TextField("Enter text", text: $text) Button("Update text") { text = "New text" } SecondView(text: $text) } } } struct SecondView: View { @Binding var text: String var body: some View { Text(text) } }
In diesem Beispiel wird @Binding verwendet, um den Wert von $text (in ContentView ) an text (in SecondView ) zu übergeben. Wenn der Benutzer also die Schaltfläche drückt, wird das Textfeld aktualisiert und der neue Text angezeigt.
@ObservedObject wird verwendet, um Eigenschaften zu markieren, die beobachtet werden und sich abhängig von externen Datenänderungen ändern können. Dieser Eigenschaften-Wrapper abonniert Änderungen im Objekt, das dem ObservableObject-Protokoll entspricht, und aktualisiert automatisch die relevanten Teile der Schnittstelle, wenn sich die Daten geändert haben. Hier ist ein kurzes Beispiel für die Verwendung von @ObservedObject :
class UserData: ObservableObject { @Published var name = "John" } struct ContentView: View { @ObservedObject var userData = UserData() var body: some View { VStack { Text("Hello, \(userData.name)!") TextField("Enter your name", text: $userData.name) } } }
In diesem Beispiel erstellen wir eine Klasse namens UserData, die einen @Published-Namen enthält. In der ContentView-Struktur erstellen wir mithilfe von @ObservedObject eine Eigenschaft namens userData mit dem Typ UserData. Wir zeigen den Wert von userData.name in einem Textfeld an und geben ihn auf dem Bildschirm aus.
Wenn der Benutzer den Wert im Textfeld ändert, aktualisiert SwiftUI automatisch den entsprechenden Teil der Schnittstelle, da die Namenseigenschaft mit @Published veröffentlicht und beobachtet wird. Das bedeutet, dass wir zum Aktualisieren der Schnittstelle keinen eigenen Code benötigen und SwiftUI dies für uns erledigen lassen.
Hinweis: Falls Sie es nicht wissen: @Published ist ein Eigenschaften-Wrapper aus dem Combine-Framework, der einer Klassen- oder Struktureigenschaft hinzugefügt werden kann und automatisch Benachrichtigungen über alle Änderungen am Wert dieser Eigenschaft an jeden sendet, der sie abonniert hat . Mit anderen Worten handelt es sich um ein Hilfsattribut für Eigenschaften, dessen Änderungen nachverfolgt werden können.
@StateObject ist ein Eigenschaften-Wrapper, der zum Initialisieren eines Klassenobjekts und zum Speichern im Ansichtszustand in SwiftUI verwendet wird. Dies bedeutet, dass das Objekt so lange gespeichert wird, wie die Ansicht existiert, und zusammen mit dieser zerstört wird. Normalerweise ist die Verwendung von @StateObject praktischer für Klassenobjekte, die für mehrere Ansichten und nicht nur für eine benötigt werden. Zum Beispiel:
class UserData: ObservableObject { @Published var name = "John" @Published var age = 30 } struct ContentView: View { @StateObject var userData = UserData() var body: some View { NavigationView { VStack { Text("Name: \(userData.name)") Text("Age: \(userData.age)") NavigationLink( destination: ProfileView(userData: userData), label: { Text("Edit Profile") }) } .navigationTitle("Home") } } } struct ProfileView: View { @ObservedObject var userData: UserData var body: some View { Form { TextField("Name", text: $userData.name) Stepper("Age: \(userData.age)", value: $userData.age) } .navigationTitle("Profile") } }
In diesem Beispiel ist UserData ein Objekt einer Klasse, die mehrere Eigenschaften enthält, die in mehreren Ansichten verwendet werden können. Die Klasse ist als ObservableObject markiert, sodass sie mit @StateObject und @ObservedObject verwendet werden kann.
In ContentView erstellen wir mithilfe von @StateObject ein neues UserData- Objekt, um den Status zwischen Übergängen zwischen verschiedenen Ansichten zu speichern. In diesem Fall zeigt ContentView Benutzerdaten an, visualisiert sie und enthält einen Link zu einer anderen Ansicht (ProfileView) , mit der die Benutzerdaten bearbeitet werden können.
In ProfileView erhalten wir mithilfe von @ObservedObject Zugriff auf dasselbe UserData- Objekt, um Benutzerdaten zu ändern. Wenn der Benutzer Daten ändert, werden diese automatisch in ContentView aktualisiert, da dasselbe UserData- Objekt verwendet wird.
Hinweis: Verwenden Sie @ObservedObject, wenn Sie Änderungen in einem Klassenobjekt aus einer Ansicht beobachten müssen, und @StateObject, wenn Sie den Status eines Klassenobjekts speichern müssen, der sich auf die Anzeige mehrerer Ansichten auswirkt.
Wenn Sie @ObservedObject anstelle von @StateObject für ein Objekt verwenden, das in mehreren Ansichten benötigt wird, verfügt jede Ansicht über eine eigene Instanz des Objekts, was zu Problemen bei der Datensynchronisierung zwischen Ansichten führen kann. Daher ist es in diesem Fall besser, @StateObject zu verwenden.
@EnvironmentObject ist ein Eigenschaften-Wrapper zum Weiterleiten von Datenobjekten durch die SwiftUI-Ansichtshierarchie. Es ermöglicht den Zugriff auf das Datenobjekt aus jeder Ansicht in der SwiftUI-Hierarchie, die zum Umgebungscontainer gehört (z. B. Szene, Ansicht, App usw.). Stellen Sie sich zum Beispiel vor, wir hätten eine App zur Aufgabenlistenverwaltung. Wir können eine Root- ContentView haben, die eine Liste von Aufgaben und die Möglichkeit enthält, neue Aufgaben zu erstellen. Dazu erstellen wir eine separate TaskListView- Ansicht, die die Liste der Aufgaben und einen Button zum Hinzufügen neuer Aufgaben anzeigt. Nach dem Hinzufügen einer neuen Aufgabe sollte der Benutzer zum Bildschirm „Aufgabe hinzufügen“ weitergeleitet werden, sodass wir eine separate AddTaskView- Ansicht erstellen.
Um das UserManager- Objekt an alle drei Ansichten zu übergeben, können wir seine Instanz in ContentView erstellen und es dann als Parameter sowohl an TaskListView als auch an AddTaskView übergeben. Dies kann jedoch zu einem Problem werden, wenn wir uns entscheiden, noch mehr verschachtelte Ansichten hinzuzufügen, da wir UserManager durch viele Zwischenansichten leiten müssen.
Stattdessen können wir @EnvironmentObject verwenden, um UserManager durch die Ansichtshierarchie nach unten zu leiten. Auf diese Weise können alle Ansichten, die Zugriff auf UserManager benötigen, diesen einfach als @EnvironmentObject deklarieren und bei Bedarf verwenden.
struct TaskManagerApp: App { @StateObject var userManager = UserManager() var body: some Scene { WindowGroup { ContentView() .environmentObject(userManager) } } } struct ContentView: View { var body: some View { NavigationView { TaskListView() } } } struct TaskListView: View { @EnvironmentObject var userManager: UserManager var body: some View { List(userManager.tasks) { task in TaskRow(task: task) } .navigationBarTitle("Tasks") .navigationBarItems(trailing: Button(action: { // Navigate to AddTaskView }) { Image(systemName: "plus") } ) } } struct AddTaskView: View { @EnvironmentObject var userManager: UserManager var body: some View { // Add new task using userManager } }
Nun wird das UserManager- Objekt automatisch über @EnvironmentObject an TaskListView und AddTaskView übergeben. Beachten Sie, dass wir den Status von UserManager in einer Ansicht ändern können und die Änderungen automatisch in der anderen Ansicht widergespiegelt werden.
Der Artikel behandelte die grundlegenden SwiftUI-Eigenschafts-Wrapper: @State, @Binding, @ObservedObject, @StateObject, @EnvironmentObject.
Diese Eigenschaften-Wrapper bilden die Grundlage für die Arbeit mit dem App-Status in SwiftUI. Verwenden Sie diesen Artikel als Spickzettel, um die grundlegenden Eigenschaften-Wrapper zur Hand zu haben, die für die Entwicklung von Apps mit SwiftUI erforderlich sind. Durch die Anwendung dieses Wissens können Sie komplexere Benutzeroberflächen mit sich dynamisch ändernden Zuständen erstellen und Daten aus Ihren Modellen in SwiftUI integrieren.