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
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章