[SwiftUI 开发] @State @Binding @ObservedObject @EnvironmentObject

@State

@State 属性包装器, struct的属性是不可以改变的,在SwiftUI中如果想改变属性,需要加上@State。而且当 @State 装饰过的属性发生了变化,SwiftUI 会根据新的属性值重新创建视图 

struct ContentView: View {
    @State var title = 0
    var body: some View {
        Button {
            title = title + 1
        } label: {
            Text("\(title)")
        }
        .font(.system(size: 38))
        .foregroundColor(.white)
        .frame(width: 88, height: 88)
        .background(Color.yellow)
        .cornerRadius(44)
    }
}

[SwiftUI 开发] @State @Binding @ObservedObject @EnvironmentObject_第1张图片

@Binding

@Binding 属性修饰器, 在 Swift 中值的传递形式是值类型传递方式。但是通过 @Binding 修饰器修饰后,属性变成了一个引用类型,传递变成了引用传递,这样父子视图的状态就能关联起来了。

struct ContentView: View {
    @State var title = 0
    var body: some View {
        UserButton(title: $title) {
            title = title + 1
        }
    }
}

  
struct UserButton: View {
    
    @Binding var title: Int
    let action: () -> Void
    
    var body: some View {
        Button(action: action) {
            Text("\(title)")
                .font(.system(size: 38))
                .foregroundColor(.white)
                .frame(width: 88, height: 88)
                .background(Color.yellow)
                .cornerRadius(44)
        }
    }
}

效果和上图一样

@ObservedObject

@Published

@ObservedObject 和@Published 相当于KVO注册监听,@ObservedObject修饰一个对象,那就是注册了监听, @Published修饰一个对象,表示这个对象可以被监听。这俩是一对。
想要使用@ObservedObject,必须实现ObservableObject 协议。

struct ContentView: View {
    
    @ObservedObject var person: Person
    
    var body: some View {
        VStack{
            Text(person.name)
            
            Button{
                person.name = "韩梅梅"
            } label: {
                Text(person.name)
                    .font(.system(size: 38))
                    .foregroundColor(.white)
                    .frame(width: 188, height: 88)
                    .background(Color.yellow)
                    .cornerRadius(10)
            }
        }
    }
}

  
class Person: ObservableObject {
    @Published var name: String = "小明"
}

[SwiftUI 开发] @State @Binding @ObservedObject @EnvironmentObject_第2张图片

@EnvironmentObject

@EnvironmentObject 环境变量,创建对象时,通过.environmentObject(person())传值。在它所有的子界面都可以用@EnvironmentObject来接收person对象。它是通过Environment查找person对象的

* 值得注意的是,push到另一个界面是不行的,必须要在同一个界面,因为push到的这个新View,不属于它的子View

let person = Person()
ContentView().environmentObject(person)

struct ContentView: View {
    @EnvironmentObject var person: Person
    var body: some View {
        VStack{
            ContentView2()
            
            Button{
                person.name = "韩梅梅"
            } label: {
                Text(person.name)
                    .font(.system(size: 38))
                    .foregroundColor(.white)
                    .frame(width: 188, height: 88)
                    .background(Color.yellow)
                    .cornerRadius(10)
            }
        }
    }
}


struct ContentView2: View {
    @EnvironmentObject var person: Person
    var body: some View {
        VStack{
            Button{
                person.name = "李雷"
            } label: {
                Text(person.name)
                    .font(.system(size: 38))
                    .foregroundColor(.white)
                    .frame(width: 188, height: 88)
                    .background(Color.yellow)
                    .cornerRadius(10)
            }
        }
    }
}

[SwiftUI 开发] @State @Binding @ObservedObject @EnvironmentObject_第3张图片

 @Environment

根据@Environment我们不仅可以拿到自定义的属性,还可以拿到系统属性

@Environment(\.presentationMode) var presentationMode: Binding

// 比如我们需要dismiss时,就需要拿到系统presentationMode对象
presentationMode.wrappedValue.dismiss()


// 可以拿到系统ColorScheme对象
@Environment(\.colorScheme) var colorScheme: ColorScheme

你可能感兴趣的:(SwiftUI,swift,开发语言,ios)