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

    技术2022-07-11  74

    对于这三个特性,我们可以简单记录一下,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 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    Processed: 0.010, SQL: 9