SwiftUI

SwiftUI 学习 - @State,@Binding,@St

2022-07-14  本文已影响0人  songzi

为了让数据更新后,自动更新画面,需要用到一些特殊的修饰符。

@State

@State,一般用于修饰本画面内部的私有属性(private)。这些私有属性的生命周期和本画面一致。属性的初始化,修改等操作,都是在本画面内完成,并不希望其他画面去碰这些数据,但这个画面的子画面除外。

struct ContentView: View {
    @State private var isFavorite = false
    
    var body: some View {
        HStack {
            Text("Click The Star")
            Button {
                isFavorite.toggle()
            } label: {
                Label("Change Favorite", systemImage: isFavorite ? "star.fill" : "star")
                    .labelStyle(.iconOnly)
                    .foregroundColor(isFavorite ? .yellow : .gray)
            }
        }
    }
}

@Binding

@Binding,一般用于修饰引用父画面的属性为自己所用,并且修改后能反馈给父画面。

struct ContentView: View {
    @State private var isFavorite : Bool = false
    
    var body: some View {
        VStack {
            HStack {
                Text("Click The Star In Me")
                Button {
                    isFavorite.toggle()
                } label: {
                    Label("Change Favorite", systemImage: isFavorite ? "star.fill" : "star")
                        .labelStyle(.iconOnly)
                        .foregroundColor(isFavorite ? .yellow : .gray)
                }
            }
            
            ContentSubView(isFavorite: $isFavorite).padding()
        }
        
    }
}

struct ContentSubView: View {
    @Binding var isFavorite : Bool
    
    var body: some View {
        HStack {
            Text("Click The Star In SubView")
            Button {
                isFavorite.toggle()
            } label: {
                Label("Change Favorite", systemImage: isFavorite ? "star.fill" : "star")
                    .labelStyle(.iconOnly)
                    .foregroundColor(isFavorite ? .yellow : .gray)
            }
        }
    }
}

ContentView 和 ContentSubView 的 isFavorite 是完全同步的。但是 ContentSubView 中的 isFavorite 是从 ContentView 传来的,而且必须使用 $isFavorite 这种写法。

@StateObject

和@State类似,用于修饰继承了ObservableObject 协议的对象。

final class User: ObservableObject {
    @Published var name = ""
    
    init(name: String) {
        self.name = name
    }
}

struct ContentView: View {
    @StateObject private var user: User = User(name: "Jacky Liu")
    
    var body: some View {
        VStack {
            HStack {
                Text(user.name)
                Button {
                    user.name = "Linda"
                } label: {
                    Text("Change Name")
                }
            }
        }
    }
}

@EnvironmentObject

@EnvironmentObject,是引用环境中的继承了ObservableObject 协议的对象为自己所用,使用 view 的 environmentObject 函数,将对象放入环境中。

final class User: ObservableObject {
    @Published var name = ""
    
    init(name: String) {
        self.name = name
    }
}

struct ContentView: View {
    @EnvironmentObject var user: User
    
    var body: some View {
        VStack {
            HStack {
                Text(user.name)
                Button {
                    user.name = "Linda"
                } label: {
                    Text("Change Name")
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(User(name: "Jack Liu"))
    }
}

@ObservedObject

@ObservedObject,一般用于修饰引用其他画面的继承了ObservableObject 协议的对象为自己所用,并且修改后能反馈给其他画面。

final class User: ObservableObject {
    @Published var name = ""
    
    init(name: String) {
        self.name = name
    }
}

struct ContentView: View {
    @StateObject var user: User = User(name: "Jacky Liu")
    
    var body: some View {
        VStack {
            HStack {
                Text(user.name)
                Button {
                    user.name = "Linda"
                } label: {
                    Text("Change Name")
                }
            }
            
            ContentSubView(user: self.user).padding()
        }
    }
}

struct ContentSubView: View {
    @ObservedObject var user: User
    
    var body: some View {
        HStack {
            Text(user.name)
            Button {
                user.name = "Linda"
            } label: {
                Text("Change Name In Subview")
            }
        }
    }
}

总结:

上一篇 下一篇

猜你喜欢

热点阅读