前言

在 SwiftUI 中,特点用于增强和办理视图的状况,以及处理视图与数据模型之间的绑定和交互。
常见的特点包装器有 @State@Binding@Published@StateObject@EnvironmentObject

@State阐明

@State为特点供给了一种声明性的方法来更新视图,而且会主动监视其值的改动以进行视图改写。

在视图结构体中声明一个特点,并用@State特点包装器进行润饰。

struct ContentView: View {
    @State private var count = 0
    var body: some View {
        Text("Count: (count)")
        Button(action: {
            count += 1
        }) {
            Text("Increment")
        }
    }
}

还能够将@State特点包装器与其他视图元素一起运用,例如文本字段、滑块等。如下所示,咱们经过$name绑定了给了TextField,保证在用户输入的内容改动时,得到输入框的内容。

struct ContentView: View {
    @State private var name = ""
    var body: some View {
        VStack {
            TextField("Enter your name", text: $name)
            Text("Hello, (name)!")
        }
    }
}

@Binding阐明

@Binding用于在视图之间传递和同享数据。它供给了一种同步更新数据的机制,使得不同视图中的数据一直坚持一致。比方咱们将父视图A的值,传递给子视图B。在B视图的更新的时候告知父视图。那么咱们就能够选用此方法。

struct ParentView: View {
    @State private var isToggleOn = false
    var body: some View {
        ChildView(isToggleOn: $isToggleOn)
    }
}
struct ChildView: View {
    @Binding var isToggleOn: Bool
    var body: some View {
        Toggle(isOn: $isToggleOn) {
            Text("Toggle")
        }
        if isToggleOn {
            Text("Toggle is on")
        } else {
            Text("Toggle is off")
        }
    }
}

@Published阐明

@Published用于标记那些需求被视图主动观察并呼应改动的类特点。在一个遵从ObservableObject协议的类中运用@Published润饰符时,任何对这个特点的修正都会触发该目标的objectWillChange发布告诉,从而导致所有绑定到这些特点的 SwiftUI 视图主动改写。

// 定义一个遵从 ObservableObject 协议的模型类
class MyModel: ObservableObject {
    @Published var name: String = "初始姓名"
    @Published var count: Int = 0
}
// 在 SwiftUI 视图中运用 ObservedObject 来引证这个模型
struct MyView: View {
    @ObservedObject var model: MyModel
    var body: some View {
        VStack {
            TextField("输入姓名", text: $model.name)
            Text("姓名是:(model.name)")
            Button("点击计数") {
                model.count += 1
            }
            Text("点击次数:(model.count)")
        }
    }
}
// 创立模型实例并在视图中运用
struct ContentView: View {
    let myModel = MyModel()
    var body: some View {
        MyView(model: myModel)
    }
}

@StateObjec阐明

@StateObject用于办理类实例生命周期的一个特点包装器,它在 SwiftUI 视图的生命周期中创立并维护一个指定类型的单例目标。这个目标遵从ObservableObject协议,其意图是保证即使视图被重建或从头创立(例如由于导航、设备旋转或者状况更改),相关的目标也会继续存在,而且其状况坚持不变。

@StateObject首要用于那些需求耐久化存在的数据模型或者是网络恳求、定时器等异步操作的成果。当运用@StateObject时,SwiftUI 会在初次创立视图时初始化该目标,并在后续视图重建过程中复用同一目标实例。

如果因为某些原因ContentView被从头创立,比方从后台返回到前台,@StateObject会保证同一个viewModel实例被再次运用,而不是创立一个新的实例,从而坚持了视图的状况一致性。

class MyViewModel: ObservableObject {
    @Published var message = "初始音讯"
    init() {
        // 或许进行的数据加载、网络恳求或其他初始化工作
    }
}
struct ContentView: View {
    @StateObject private var viewModel = MyViewModel() // 创立并维护 MyViewModel 的实例
    var body: some View {
        VStack {
            Text("音讯:(viewModel.message)")
            Button("更新音讯") {
                viewModel.message = "新音讯"
            }
        }
    }
}

@EnvironmentObject阐明

@EnvironmentObject允许在视图层级中同享一个遵从ObservableObject协议的目标。这个目标的状况改动能够触发相相关的视图更新。经过在环境(environment)中注入这些目标,你能够在多个视图间轻松传递和同享数据。简单来说它相当于一个大局变量的声明

运用@EnvironmentObject的根本过程:

  1. 创立一个遵从ObservableObject的类,并定义你需求同享的数据模型或状况。
  2. 在你的使用根视图或者某个高层级视图中设置环境目标。这通常经过.environmentObject()视图润饰符来完成。
  3. 在需求访问该环境目标的子视图中声明@EnvironmentObject特点。
class UserSettings: ObservableObject {
    @Published var userName = "默认用户"
}
// 设置环境目标的根视图
struct ContentView: View {
    @StateObject var userSettings = UserSettings()
    var body: some View {
        VStack {
            Text("欢迎来到主界面!")
            NavigationLink(destination: SubView()) {
                Text("跳转到子视图")
            }
        }
        .environmentObject(userSettings) // 将 UserSettings 目标放入环境
    }
}
// 子视图从环境中获取并显示用户设置
struct SubView: View {
    @EnvironmentObject var userSettings: UserSettings
    var body: some View {
        VStack {
            Text("用户名:(userSettings.userName)")
            Button("更改用户名") {
                userSettings.userName = "新用户名"
            }
        }
    }
}

总结

@State特点包装器在 SwiftUI 中扮演着要害人物,它完成了特点与视图间的强绑定关系。这意味着,被@State润饰的特点被视为视图层次中的仅有且真实的数据源。当这个状况发生改动时,SwiftUI 能够主动触发相相关视图的改写以反映最新的数据状况。在视图层级结构中,父视图和子视图间的数据传递是根据值传递的方法进行的,即子视图经过获取父视图@State变量的一个副本来展现和操作其内容。

@Binding特点包装器则供给了一种更为灵活的父子视图间通信机制。不同于值传递,它是经过指针(引证)的方法来完成双向数据绑定。这样,在子视图内部对@Binding类型变量的修正会直接反映到父视图的原始状况上,保证了数据的一致性。

@ObservableObject是一个用于目标等级的呼应式编程工具。遵从该协议的目标能够在其特点发生改动时发送告诉给所有相关的观察者。这种机制使得多个视图能够监听同一个目标的状况改动,并据此做出相应的更新。这在复杂的视图结构和数据模型中尤为有用,因为它允许你在不同视图之间同享并实时同步同一份数据。

最后,@EnvironmentObject则为大局数据同享供给了便当途径。它将数据封装到环境目标中,并在整个视图层级结构中均可访问。经过.environmentObject()方法注入环境目标后,任意嵌套深度的视图都能够声明并运用@EnvironmentObject来获取这些同享数据。这一特性使@EnvironmentObject成为办理多视图间同享状况的理想选择,尤其在需求跨越多个视图层级传递或同享数据的情况下。