簡體   English   中英

SwiftUI – @State 與 @Binding

[英]SwiftUI – @State vs @Binding

我正在學習 iOS 使用 Swift 和 SwiftUI 進行編程。我知之甚少,而且我對@State@Binding之間的區別感到非常困惑。

如果我理解正確,@Binding 在技術上@State @Binding它不會更新視圖。 如果是這樣,那么如果我可以使用@State來做同樣的事情,為什么我需要@Binding呢?

@State@Binding都是屬性包裝器。

@狀態

  • 它用於每次更新變量的值。
  • 我們也可以說這是一種雙向綁定。
  • 如果我們更改屬性 state 那么 SwiftUI 將自動重新加載視圖主體。
  • 它用於簡單的屬性,如字符串、整數和布爾值。

@捆綁

  • 使用它,您可以訪問另一個視圖的 state 屬性。
  • 它將為您提供變量的讀寫訪問權限。

SwiftUI 是一個聲明式的面向組件的框架。 您必須忘記 MVC,其中控制器在視圖和 model 之間進行調解。 SwiftUI 使用 diffing 算法來了解更改並僅更新相應的視圖。

@狀態

  • State 屬性連接到視圖。 視圖永久讀取 State 屬性。 這意味着每次更改/更新@State 屬性時,視圖都會重新渲染,並最終根據@State 的數據顯示內容。
  • State 僅可訪問特定視圖。
  • 字符串、整數和布爾值等簡單屬性屬於單個視圖 - 標記為私有。
  • 所有標記為 State 的字段都存儲在特殊分隔的 memory 中,只有對應的視圖才能訪問和更新它們。

@捆綁

  • BindableObject 協議,它需要一個 didChange 屬性。 它可以在環境中使用它並在它發生變化時立即重建視圖。
  • didChange 屬性應該是一個 Publisher,它是 Apple 新的 Reactive 框架的一部分,稱為 Combine。
  • Publisher 的主要目標是在發生變化時通知所有訂閱者。 一旦出現新值,SwiftUI 將重建視圖。

@環境對象

  • 它是稱為環境的功能的一部分。 您可以使用所有需要的服務類填充您的環境,然后從該環境中的任何視圖訪問它們。
  • 環境中的每個視圖都可以訪問 @EnvironmentObject。
  • @EnvironmentObject 在其他地方創建的屬性,例如共享數據。 如果丟失,應用程序會崩潰。
  • 環境是使用 SwiftUI 進行依賴注入的正確方法。

State視為您視圖的唯一真實來源,作為變異變量並使視圖無效以反映 state 的手段。

另一方面, Binding視圖與其底層 model 之間的雙向連接 一種改變不受視圖管理的State的方法(例如,反映和控制控件本身不知道其存儲或來源的布爾值的Toggle

最后,您可以使用$前綴運算符從任何State獲取Binding

在它們之間進行選擇的簡單指南是:

我是否需要修改我私有的值? => State

我需要修改其他視圖的 State 嗎? => 綁定

State

  • @State關鍵字允許我們詢問 SwiftUI 來監控屬性的值。 一旦值發生變化, View將失效並以有效的方式再次呈現。
  • 給定類型的持久值,視圖通過它讀取和監視該值。
  • 這只是另一個概述事實來源的@propertyWrapper
  • 當您使用 state 時,框架會為變量分配持久性存儲並將其作為依賴項進行跟蹤……您始終必須指定一個初始常量值

捆綁

  • @Binding$ -prefix 允許將State屬性傳遞給嵌套的子對象。
  • 一個值的管理者,它提供了一種改變它的方法。
  • @Binding另一個顯式依賴於@propertyWrapper的 @propertyWrapper。
  • 通過使用Binding屬性包裝器,您可以定義對事實源的顯式依賴而不擁有它,此外,您不需要指定初始值,因為綁定可以從 state 派生。

供您參考的鏈接: Medium

我想提供一個非常簡短的“實際用途”解釋,這有助於我清除它。 我沒有定義狀態/綁定,我只是指出了很大的區別。

@State擁有價值,即“真相的來源”

@Binding傳遞值,用作管道。

關於@State的一件重要事情:更改將觸發重繪。 更改@State的值將導致整個視圖“重新執行”。

State簡單屬性,如 string、整數和布爾值 屬於單個視圖 - 標記為私有

綁定復雜的屬性,如自定義類型在許多視圖中共享數據。 引用類型需要

在其他地方創建的EnvironmentObject屬性(例如共享數據)如果丟失,應用程序將崩潰。

Here is the notes I have prepared for myself,

@State:

  • We need to use this inside a view struct
  • It’s recommended to make as private
  • We should provide default value
  • Can be used as binding
  • This is meant to store simple types like String, Int, Bool, etc...

@Binding:

  • This is used to share common data between the views
  • Best example is, presenting an sheet from View 1 and initiating dismiss action from View 2
  • No need for default value as will set it from another view

Thanks!

關於@State 和@Binding

想象一下您有兩個 SwiftUI 視圖的情況。 在第一個視圖中,您聲明了一個count變量,在第二個視圖中,您創建了一個Tap Me按鈕。 單擊按鈕時,應更新第一個視圖中的count 要實現此邏輯,您需要在第一個視圖中使用@State屬性包裝器,並在第二個視圖中使用@Binding屬性包裝器。

@State允許在本地操作少量value type的數據。 @State直接創建和管理值,因此它是Source of Truth @Binding也指的是value type的數據,但屬於不同的視圖。 @Binding不是事實的來源。 為了將@State屬性提供給Binding<T>您需要使用$運算符(即它看起來像$count )。 @Binding在屬性和另一個視圖之間創建雙向連接。

這是代碼:

在此處輸入圖像描述

 import SwiftUI struct FirstView: View { @State private var count: Int = 0 var body: some View { ZStack { Color.black.ignoresSafeArea() VStack { SecondView(counter: $count).frame(width: 300, height: 100) Text("Tapped \(count) times").foregroundColor(.white) } } } } struct SecondView: View { @Binding var counter: Int var body: some View { ZStack { Color.yellow Text("Tap Me").onTapGesture { counter += 1 } } } }

除了前面提到的屬性包裝器之外,借助所謂的“三位一體”套件—— @StateObject@Published@ObservedObject ,也可以實現類似的結果。

屬性包裝器

下面的 pivot 表代表了 15 個常用的 SwiftUI 4.0 屬性包裝器的主要特性。

# 屬性包裝器 真理之源 它是干什么用的? 類型
01 @AppStorage 是的 從 UserDefaults 讀取/寫入 價值
02 @捆綁 創建雙向連接 價值
03 @環境 從系統中讀取數據
04 @環境對象 從多個視圖中讀取共享的 object 參考
05 @FetchRequest 是的 將其用於 CoreData 獲取請求
06 @FocusedBinding 在關鍵視圖中監視值 價值
07 @FocusedValue @FocusedBinding 的簡單版本 價值
08 @手勢狀態 是的 存儲活動手勢的值 價值
09 @命名空間 是的 創建一個 animation 命名空間
10 @ObservedObject 指符合 ObservableObject 的外部 class 的實例 參考
11 @已發布 是的 附加到 ObservableObject 內部的屬性 參考
12 @ScaledMetric 是的 讀取用戶的動態類型設置 價值
13 @SceneStorage 是的 恢復系統狀態的輕量級數據 價值
14 @狀態 是的 在本地操作視圖的數據 價值
15 @StateObject 是的 存儲一個符合 ObservableObject 的新實例 參考

@State 和@Binding 將變量轉換為流。 帶有@State 的變量是一個事件源,每次修改它時都會產生“值已更改”。 默認情況下,此事件連接到“更新視圖”,因此每次修改變量時,都會引發事件並刷新視圖。

帶有 @Binding 的變量充當sourcesink ,因此您可以將另一個變量的事件“綁定”到其中。 當您通過 $ 將變量傳遞給視圖時,您要求 swiftUI 將 $thisVairable 的事件提供給 @Binding 變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM