SwiftUI數據流與界面綁定


SwiftUI 中引入了一個關鍵字 @State 來作為數據綁定的標識。當一個被綁定的數據被改變時,相關聯的視圖會重新計算它自己的 body 內容;反過來,當視圖主動去改變綁定在數據上的屬性時,這個數據也會隨之變化

SwiftUI 的數據流模型是基於下面兩點原則來構建的:

Data Access as a Dependency:以依賴的形式訪問數據 Source of Truth:單一數據源

展開來看: Data Access as a Dependency 在多數情況下,我們的視圖是需要根據某些狀態來動態變化顯示樣式的,比如對於 Switch 來說,改變它的 on 屬性可以讓它顯示當前的開關狀態。

對於這種情況,on 屬性就應該作為 Switch 的依賴而存在,否則這個控件除了長得好看就一無是處了。所以在 SwiftUI 里,屬性會被描述為視圖的依賴,這意味着我們的注意力可以從屬性和視圖的關聯里抽身出來,集中在建立更好的用戶體驗上。

Source of Truth 同一組視圖里的數據都是來自於同一個數據源的

使用 @State 標記的變量會自動生成一個以 $ 作為前綴的新變量,這個新變量本質上是一個 Computed Value,實現了雙向綁定的機制

通過聲明變量為 @Binding,我們就告訴了編譯器這個變量是從外部傳入的可以被綁定的參數,相當於 React 里的 Props 聲明

變量的聲明和使用都是在一個結構體里面完成的,這就意味着這個視圖與 視圖 是解偶的

 

SwiftUI數據流溫故知新 - 屬性包裝

@State

@State屬性允許修改Struct的屬性,這些屬性在普通的Struct里面是不允許修改的。當把@State放置到屬性前,該屬性實際上會被放到Struct的外部存儲起來,這意味着SwiftUI能夠隨時銷毀和重建Struct而不會丟失屬性的值。

@State包裝的屬性通常是設置成私有的,不讓外部使用。如果想讓外部使用,則應該使用@ObservedObject和@EnvironmentObject,他們能夠使外部修改屬性后,狀態能夠得到改變。

建議把@State包裝的屬性都設置成私有

@Published

@Published是SwiftUI最有用的包裝之一,允許我們創建出能夠被自動觀察的對象屬性,SwiftUI會自動監視這個屬性,一旦發生了改變,會自動修改與該屬性綁定的界面。

1.首先需要遵循ObservableObject屬性

class Bag: ObservableObject { var items = [String]() }

2.包裝屬性

class Bag: ObservableObject { @Published var items = [String]() }

這樣就完成了。@Published包裝會自動添加willSet方法監視屬性的改變。

@ObservedObject

@ObservedObject告訴SwiftUI,這個對象是可以被觀察的,里面含有被@Published包裝了的屬性。

@ObservedObject包裝的對象,必須遵循ObservableObject協議。也就是說必須是class對象,不能是struct。

@ObservedObject允許外部進行訪問和修改。

@EnvironmentObject

@EnvironmentObject包裝的屬性是全局的,整個app都可以訪問

需要注意的是,不需要給定默認值,由於該屬性是整個app都可以訪問的,SwiftUI會自動的從環境中取出來。

當****有這樣一個場景,A->B->C->D->E->F,A界面的數據要傳遞給F界面,假如使用@ObservedObject包裝,則需要一層一層傳遞,而使用@EnvironmentObject則不需要,直接在F界面,通過SwiftUI環境直接取出來就行。

需要注意的是,當界面顯示時,就會去環境中取,但是,假如之前沒有把屬性放到環境中,則程序會崩潰。

@Environment

@Environment與@EnvironmentObject作用是不同的,@Environment是從環境中取出預定義的值,比如獲得當前是暗黑模式還是正常模式,屏幕的大小等等。

@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.managedObjectContext) var managedObjectContext

@Binding

@Binding也是非常重要的一個包裝,聲明一個屬性是從外部獲取的,並且與外部是共享的。相當於外部傳過來的時候,不是傳遞的值。任何一方修改都會讓SwiftUI的監視生效。

@GestureState

@GestureState能夠讓我們傳遞手勢的狀態,雖然使用@State也能實現,但@GestureState能讓手勢結束后我們回到最初的狀態。

設置屬性,設置zero意味着手勢結束后,會回到最初的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM