SwiftUI开发-@EnvironmentObject、ObservableObject、@Published理解

对于这三个特性,我们可以简单记录一下,EnvironmentObject修饰属性是当前的环境变量,并在它自己以及它的子视图都可以直接使用,也可以叫做当前当前视图全局变量。下面我们看一个编辑学生姓名的例子:

先定义一个学生数据模型,如下:

class Student: ObservableObject {
    @Published var name = ""
}

然后在写一个编辑框,编辑学生的姓名:

struct EditStudentView: View {
    @EnvironmentObject var user: Student
    var body: some View {
        TextField("请输入学生姓名", text: $user.name)
    }
}

然后在创建一个显示学生姓名的视图:

struct DisplayStudentView: View {
    @EnvironmentObject var user: Student
    var body: some View {
        Text(user.name).frame(width: 200, height: 20, alignment: .center).border(Color.red, width: 1).background(Color.green)
    }
}

最后我们在ContentView.swift这个文件里添加这两个视图:

struct ContentView: View {
    let student = Student()
    var body: some View {
        VStack(alignment: .leading) {
            
            EditStudentView().frame(width: 300.0, height: 40.0).padding(.horizontal, 20.0).border(Color.black, width: /*@START_MENU_TOKEN@*/1/*@END_MENU_TOKEN@*/).cornerRadius(/*@START_MENU_TOKEN@*/3.0/*@END_MENU_TOKEN@*/).padding().environmentObject(student)
            
            DisplayStudentView().frame(width: 300, height: 40, alignment: .center).border(/*@START_MENU_TOKEN@*/Color.black/*@END_MENU_TOKEN@*/, width: /*@START_MENU_TOKEN@*/1/*@END_MENU_TOKEN@*/).padding().environmentObject(student)
            Spacer()
        }
        
    }
}

最后我们通过xcode的预览功能,查看效果。在这里我们要说一下,我们发现编辑和显示两个视图他们之间并没有直接的关系,但是他们都是Content的子视图,而且他们两个都是获取的Content的变量,这样在环境变量中就只有一份内容,所以才会在编辑的时候能及时的显示出姓名。下面我们在添加一层。

在显示的视图上修改成如下:

struct DisplayStudentView: View {
    var body: some View {
        StudentNameView()
    }
}

struct StudentNameView: View {
    @EnvironmentObject var user: Student
    var body: some View {
        Text(user.name)
    }
}

把Content改成如下的形式:

struct ContentView: View {
    @EnvironmentObject var student: Student
    var body: some View {
        VStack(alignment: .leading) {
            
            EditStudentView().frame(width: 300.0, height: 40.0).padding(.horizontal, 20.0).border(Color.black, width: /*@START_MENU_TOKEN@*/1/*@END_MENU_TOKEN@*/).cornerRadius(/*@START_MENU_TOKEN@*/3.0/*@END_MENU_TOKEN@*/).padding()
            
            DisplayStudentView().frame(width: 300, height: 40, alignment: .center).border(/*@START_MENU_TOKEN@*/Color.black/*@END_MENU_TOKEN@*/, width: /*@START_MENU_TOKEN@*/1/*@END_MENU_TOKEN@*/).padding()
            Spacer()
        }
        
    }
}

再次预览的时候,我们发现和上边的效果一样。通过这一点的细微的变化,我们也许能够明白点这里的问道了吧,实践是检验真理的唯一标准。慢慢体会。。。

下面转载一个博客的一段话:

  • @State和@ObservableObject之间有一些细微的差异。这些都是很重要的,因为它们都有不同的用途。首先,@State在视图本地。值或数据在视图中本地保存。它由框架管理,由于它存储在本地,因此它是一个值类型。但是@ObservableObject在视图外部,并且不存储在视图中。它是一种引用类型,因为它不在本地存储,而只是具有对该值的引用。这不是由框架自动管理的,而是开发人员的责任。这最适用于外部数据,例如数据库或由代码管理的模型。

  • @Binding也在视图内,但是与@State区别在于@Binding用于不通视图之间的参数传递。@Binding 和@ObservedObbjecg一样都是传递引用。

  • @EnvironmentObject 可以理解为全局变量
    具体细微差别,大家可以访问demo页面体验用途的不同。



作者:iCloudEnd
链接:https://www.jianshu.com/p/9915b91495da
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(SwiftUI)