簡述 SwiftUI 的 State Property Wrapper

法蘭克的 iOS 世界
4 min readFeb 8, 2021

--

Photo by Lisa Fotios on Pexels

SwiftUI 官方文件有一章節在講述 State and Data Flow,其主要在談如何將 Data 和 UI 做綁定,什麼意思呢?指的是,當 Data 有變化時,UI 也會重新計算並更新它認為需要被更新的 UI,聽起來很酷很方便對吧!?。在 SwiftUI 釋出前,如果要將 Data 和 UI 做綁定的話,有很多方式可實作,包括 KVO、Notification、Delegate、Property Observers 等等,這些方式都得額外撰寫。Apple 為了將其做法統一,在 SwiftUI 裡釋出許多將 Data 和 UI 做綁定的工具供開發者使用,其工具非常多,例如今天要介紹的 State Property Wrapper(屬性修飾器) 就是其中之一,當然還有很多很多,就端看使用情境為何,並選擇適合的工具來用,就讓法蘭克從 State 開始講起吧。

用 State Property Wrapper 的來宣告此屬性,並加上 private 用來表示僅有 在 Struct 內部才可以設定它。如果沒有加上 private 且外部存取到它,將會導致 App 閃退的。

@State private var isPlaying: Bool = true

當如上這樣宣告時,聰明的 Property Wrapper 會去檢查與其相關的 UI 是否需要被更新。如下產生一個按鈕,當點擊按鈕的時侯,去改變 isPlaying 的值,當 isPlaying State Property 變動時,則會自動更新受影響的 Views。

Button(action: {    isPlaying = !isPlaying // 點擊按鈕時,如果 isPlaying 為 false 則設為 true;反之,則會 false}) {
// 當 isPlaying State Property 變動時,則會自動更新受影響的 Views
Image(systemName: isPlaying ? “stop.fill” : “play.fill”) .resizable() .frame(width: 25, height: 25) .foregroundColor(.white)}

接著把上面的程式碼搬到 ContentView 裡,並試著用 Preview 看看 Data 和 UI 的變化為何?以下為一播放器,當音樂播放中,出現暫停按鈕,反之,則出現開始按鈕。

Preview 結果

除了上述方式外,亦可以透過 $+propertyName 來存取 Property Wrapper 的值。不過,只有支援 Binding 的 Views 可使用,例如 Toggle View 的初始方法。

Toggle view’s init method

試著透過 Binding Property Wrapper 的方式來初始化 Toggle 看看

Toggle(isOn: $isPlaying, label: {    Text(isPlaying ? “Stop” : “Play”)})

接著把上面的程式碼搬到 ContentView 裡,並試著用 Preview 看看 Data 和 UI 的變化為何?以下程式碼透過 Toggle 的切換來改變 isPlaying 的值,並檢查與其相關的 UI 是否要更新。

Preview 結果

總結

State Property Wrapper 總是適用於 Value Type 的 Property;並不適用於 Reference Type 的 Property。因其只有當記憶體位置改變時,才會 Trigger 的特性存在。

果您喜歡我的文章,請多按幾下「拍手」給我鼓勵,或是按「follow」讓我持續提供好文章給您。若有任何問題也歡迎隨時提出。

--

--