SwiftUI数据流和绑定备忘
SwiftUI数据流和绑定备忘
@State,@Binding,@ObservableObject,@EnvironmentObject,@@Environment备忘与实例
1. @State 和 @Binding
@State 修饰当前视图里面的一个状态量,当改变这个状态量后,当前视图自动刷新
@State 修饰的状态量可以传给子视图,这个子视图中接受的属性必须要用@Binding修饰,传递给子视图时,需要用$在参数名前面表示是值传递
下面代码运行时,点击Update State之后,两个Text内容都变成了"State Changed By Son"
import SwiftUI
struct Me: View {
@State var myState:String = "Initial State" //父视图@State修饰 状态量
var body: some View {
VStack{
Text("Parent state: \(myState)")
Divider()
MySon(stateFromParent:self.$myState) // 父视图状态量传递给子视图时,用$符修饰
}
}
}
struct MySon:View {
@Binding var stateFromParent:String //子视图用@Binding修饰从父视图接收的状态量
var body: some View {
VStack {
Text("Son State:\(stateFromParent)")
Button("Update State") {
self.stateFromParent = "State Changed By Son"
}
}
}
}
struct Me_Previews: PreviewProvider {
static var previews: some View {
Me()
}
}
2. ObservableObject,@ObservedObject和@Published
ObservableObject是一个protocol,实现ObservableObject的类中的使用@Published修饰的property会被SwiftUI监听,
一旦@Published修饰的property发生改变,所有关联到这个ObservableObject对象的View都会被自动更新.需要注意的是,
View关联ObservableObject对象的方式是使用@ObservedObject修饰property.@ObservedObject修饰对象可以传递给各个独立的
View,传参时参数名前不需要加$符了,当初正常的引用参数传递.使用ObservableObject,@ObservedObject和@Published可以完全替代@State和@Binding.
下面代码运行时,点击Update State之后,两个Text内容都变成了"State Changed By Son"
import SwiftUI
struct Me: View {
@ObservedObject var myState:StateHolder = StateHolder(currentState:"State of Me") //@ObservedObject修饰的对象可以被多个独立view使用,不仅仅是子View
var body: some View {
VStack{
Text("Parent state: \(myState.currentState)") //这里myState前面不需要$了
Divider()
MySon(stateOfMySon:myState)
}
}
}
struct Me_Previews: PreviewProvider {
static var previews: some View {
Me()
}
}
struct MySon:View {
@ObservedObject var stateOfMySon:StateHolder
var body: some View {
VStack {
Text("Son State:\(stateOfMySon.currentState)")
Button("Update State") {
self.stateOfMySon.currentState = "State Changed By Son" //改变这个属性,会更新所有关联到stateOfMySon(其实和Me的myState是一个对象,同一个引用)的View
}
}
}
}
class StateHolder:ObservableObject {
@Published var currentState:String
init(currentState:String) {
self.currentState = currentState
}
}
3. @EnvironmentObject
@EnvironmentObject同样使用ObservableObject和@Published机制.@EnvironmentObject修饰的属性相当于从全局环境中拿数据.通过它,
我们可以避免在初始 View 时创建 ObservableObject, 而是从环境中获取 ObservableObject.这个环境是当前视图的父视图的环境.
在创建父视图时,使用.environmentObject(envObj)来设置环境参数.
同一个上下文只会存在一个类型相同的@EnvironmentObject对象,当存在多个时,子View设置的environmentObject会覆盖掉父View的相同类型的对象.
默认View中取离自己最近的父View设置的EnvironmentObject.
import SwiftUI
/**
下面例子中,A包含B,B包含C,A,B,C都有一个@EnvironmentObject currentState
首先通过VStack设置了全局的环境变量Env_Global,创建B()时重设了子环境变量Env_B,Env_B就覆盖了Env_Global
于是
A()和C()中显示state of env:Env_Global
B()中显示state of env:Env_B
*/
struct Me: View {
var body: some View {
List {
A()
B().environmentObject(StateHolder(currentState:"Env_B"))
C()
}.environmentObject(StateHolder(currentState:"Env_Global"))
.font(.system(size:20,weight:.light))
.padding(4)
}
}
struct Me_Previews: PreviewProvider {
static var previews: some View {
Me()
}
}
class StateHolder:ObservableObject {
@Published var currentState:String
init(currentState:String) {
self.currentState = currentState
}
}
struct A: View {
@EnvironmentObject var currentState:StateHolder
var body: some View {
VStack {
Text("This is A")
Text("state of env:\(currentState.currentState)")
B()
}
}
}
struct B: View {
@EnvironmentObject var currentState:StateHolder
var body: some View {
VStack {
Text("This is B")
Text("state of env:\(currentState.currentState)")
C()
}
}
}
struct C: View {
@EnvironmentObject var currentState:StateHolder
var body: some View {
VStack {
Text("This is C")
Text("state of env:\(currentState.currentState)")
}
}
}
4. @Environment
SwiftUI 本身就有很多系统级别的设定,通过 @Environment 来获取到它们.
下面代码显示zh_CN
import SwiftUI
struct Me: View {
/**
@Environment注解参数为key
*/
@Environment(\.calendar) var calendar: Calendar
@Environment(\.locale) var locale: Locale
@Environment(\.colorScheme) var colorScheme: ColorScheme
var body: some View {
return Text(locale.identifier)
}
}
struct Me_Previews: PreviewProvider {
static var previews: some View {
Me()
}
}
赞 赏 微信赞赏
支付宝赞赏
本文固定链接: https://www.jack-yin.com/coding/ios/3151.html | 边城网事