可监听的的数据属性,可以触发对应view的刷新。 用于基本数据类型,比如 Bool, Int, String
样例代码:
//声明 可监听的属性
@State private var showScore = true
Button(“ShowOrHide”) {
//修改该属性,会触发执行 使用该属性的代码
showScore = !showScore
}
if showScore {
ScorePlate(model: model).padding(.top, 20)
}
将一个 @State 属性绑定到一个 @Binding 属性上。 当双方发生改变时,都会改变另一个。
struct CategoryHome: View {
@State var showingProfile = false
var body: some View {
List {
//将 self.showingProfile 设为 true 来弹出 ProfileHost
Button("Change") {
self.showingProfile = true
}
}
.sheet(isPresented: $showingProfile) {
//将 showingProfile 绑定到 ProfileHost的 shouldHide 上,然后 ProfileHost就可以控制shouldHide来做dismiss操作了。
ProfileHost(shouldHide: $showingProfile)
}
}
}
struct ProfileHost: View {
@Binding var shouldHide : Bool
var body: some View {
Button("Close") {
// 绑定的showingProfile 也会改为false,将当前view 给dismiss掉
self.shouldHide = false
}
}
}
Binding 属性可以用常量来初始化 比如上面的 Binding:
Binding.constant(false)
Binding属性的初始化可以是
@Binding(projectedValue: .constant(1)) var currentPage : Int
init(currentPage : Binding<Int>) {
self._currentPage = currentPage
}
可监听指定类的所有属性变化情况 以刷新UI. 当@Published 属性变化时,存储该对象的变量声明为 @ObservedObject 时,使用到该实例对象代码会执行。 该属性可以从外部传入,或是View 对象自己创建。
样例代码:
//类必须实现 ObservableObject 协议
class ObserverbleModel: ObservableObject {
//需要监听的属性 声明为 @Published。只有在Published 属性变化时,才会触发声明了 @ObservedObject 属性的View 的body 重绘
@Published var score: Int = 0
var bigScore : Int = 0
}
struct ScoreText: View {
//需要监听的数据对象,声明为 @ObservedObject
@ObservedObject var model: ObserverbleModel
var body: some View {
if model.bigScore > 5 {
Text("Big good")
}
else {
Text("Big bad")
}
}
}
跟ObservedObject 一样都是可监听的。 不同的是,声明StateObject的View,必须是它创建的该对象(StateObject属性是只读的),该对象生命周期跟随View
使用ObservedObject 时,需要将对象逐个传递给子View的属性。 如果使用环境对象EnvironmentObject,则只用传递一次,该View 和它下面的子View里,声明为 EnvironmentObject的对象都能被赋值。 一个View的EnvironmentObject 只能声明一个,声明多个的话,都会指向同一个对象。 EnvironmentObject只能通过 environmentObject 方法从view 外部传入。
样例代码:
//第一级子view
struct SubEnvironmentView : View {
//声明了两个,但都会指向同一个对象
@EnvironmentObject fileprivate var data : TestBigData
@EnvironmentObject fileprivate var data2 : TestBigData
var body: some View {
VStack {
Text("SubEnvironmentView").font(.largeTitle).foregroundColor(.red)
if data.showText {
Text(data2.text).foregroundColor(.red)
}
SubEnvironmentView2()
}
}
}
//第二级子view
struct SubEnvironmentView2 : View {
@EnvironmentObject fileprivate var data : TestBigData
var body: some View {
VStack {
Text("SubEnvironmentView2").font(.largeTitle).foregroundColor(.blue)
if data.showText {
Text(data.text).foregroundColor(.blue)
}
}
}
}
//顶级view
struct StateObservedEnvironment: View {
@StateObject fileprivate var data : TestBigData = TestBigData()
@EnvironmentObject fileprivate var envData : TestBigData
var body: some View {
VStack {
Toggle(isOn: $data.showText) {
Text("开关")
}.onChange(of: data.showText) { newValue in
envData.showText = newValue
}
SubEnvironmentView()
}
}
}
//最外面,将环境对象传入
StateObservedEnvironment().environmentObject(TestBigData())
代码说明:
Button(“ShowOrHide”) {
//修改该属性,会触发执行 使用该属性的代码
showScore = !showScore //此时不会同步触发 监听者的代码块
print(“over”) //该作用域代码执行完毕后,才会触发监听代码
}
class TestBigData : ObservableObject {
var realShow : Bool = true
@Published var subData : SubTestData = SubTestData()
@Published var subDataArr = [SubTestData()]
}
//必须是struct
struct SubTestData {
var subShowFlag : Bool = true
}
PS: 如果声明为class,当subShowFlag 变化时,实际上 TestBigData 的那两个Published 属性的值并没有变化,因此无法触发 监听事件