• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • SwiftUI 數據狀態和綁定

    標簽: SwiftUI 入門  ios  swift  swiftui

    SwiftUI 數據狀態和綁定

    方案說明備注
    @State & @Binding提供 View 內部的狀態存儲應該是被標記為 private 的簡單值類型,僅在內部使用。
    ObservableObject & @ObservedObject針對跨越 View 層級的狀態共享處理更復雜的數據類型,在數據變化時觸發界面刷新。
    @EnvironmentObject對于 “跳躍式” 跨越多個 View 層級的狀態更方便地使用 ObservableObject,以簡化代碼。

    @State & @Binding

    Parent view:

    struct ParentView: View {
        @State private var foo: Bool = false
    
        var body: some View {
            VStack(spacing: 25) {
                Text("foo in Parent: \(self.foo ? "?" : "")")
                ChildView(foo: $foo)
            }
        }
    }
    

    Child view:

    struct ChildView: View {
        @Binding var foo: Bool
    
        var body: some View {
            Button("toggle foo from Child") {
                self.foo.toggle()
            }
        }
    }
    

    運行效果:

    截屏2021-01-15 10.25.15

    @ObservedObject

    Model:

    class Model: ObservableObject {
        @Published var foo: Bool = false
    }
    

    注意,@Published 是個 internal 的。在 Xcode 工程里沒事,但在 Playground 的 Sources 里寫是必須 public 的,這時可以采用下面這種手動處理的方法:

    import Combine
    
    public class Model: ObservableObject {
        public let objectWillChange = PassthroughSubject<Void, Never>()
    
        public var foo: Bool = false {
            willSet { objectWillChange.send() }
        }
    
        public init() {}
    }
    
    • let objectWillChange = PassthroughSubject<Void, Never>() 用來實現 ObservableObject 協議;
    • 給每個需要 @Published 的變量加 willSet { objectWillChange.send() }

    Parent View:

    public struct ParentView: View {
       @ObservedObject var model: Model = Model()
    
       public var body: some View {
           VStack(spacing: 25) {
               Text("foo in Parent: \(self.model.foo ? "?" : "")")
               ChildView(model: model)
           }
       }
        
        public init() {}
    }
    

    Child View:

    public struct ChildView: View {
       var model: Model
    
       public var body: some View {
           Button("toggle foo from Child") {
               self.model.foo.toggle()
           }
       }
        
        public init(model: Model) {
            self.model = model
        }
    }
    

    這里其實是利用 class 的“傳引用”特性來讓子訪問到父的 model 的,沒什么特殊的。

    @EnvironmentObject

    沿用上面 ObservableObject 的 Model:

    class Model: ObservableObject {
        @Published var foo: Bool = false
    }
    

    Parent View:

    public struct ParentView: View {
       @EnvironmentObject var model: Model
    
       public var body: some View {
           VStack(spacing: 25) {
               Text("foo in Parent: \(self.model.foo ? "?" : "")")
               ChildView()
           }
       }
        
        public init() {}
    }
    

    Child View:

    public struct ChildView: View {
       @EnvironmentObject var model: Model
    
       public var body: some View {
           Button("toggle foo from Child") {
               self.model.foo.toggle()
           }
       }
        
        public init() {}
    }
    
    

    調用 Parent 的 View:

    ParentView().environmentObject(Model())
    

    用 EnvironmentObject 讓所有子都訪問到父的 Model,可以避免逐層手動傳遞對象。

    完整源碼實現:SwiftUIDataStateAndBinding.playground

    參考

    王巍 (@onevcat)《SwiftUI 與 Combine 編程》Chapter 3:數據狀態和綁定

    版權聲明:本文為u012419550原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/u012419550/article/details/112712632

    智能推薦

    SwiftUI 超強大文章編輯組件支持多行顯示并限制行數與字符數(兼容SwiftUI1.0和SwiftUI 2.0)

    SwiftUI 超強大文章編輯組件支持多行顯示并限制行數與字符數(兼容SwiftUI1.0和SwiftUI 2.0) 實戰需求 SwiftUI的TextField和TextEditor目前都存在中文輸入問題, 如何優雅的隱藏鍵盤也是個問題? 如何獲取字符數和行數呢? 如何限制字符數和行數呢? 本文將為大家制作個可以用于生產環境的強大文本輸入框 本文價值與收獲 看完本文后,您將能夠作出下面的界面 看...

    SwiftUI實戰三:創建List視圖和導航Navigation

    系統: Mac OS 10.15.1, XCode 11.2.1,swift 5.0 寫作時間:2019-11-30 1. 說明 此例子包含元素:List視圖(代替以前的TableView), 導航。這個例子接著上一個例子SwiftUI實戰二:組合視圖和地圖視圖,把它當作詳情頁。 細節請查看官網教程 2. 元素以及代碼下載 https://github.com/zgpeace/BuildingLi...

    SwiftUI-HStack、VStack和ZStack組合用

    文章目錄 前言 效果圖 代碼 前言 個人學習 SwiftUI 的記錄,如有錯誤,請指教哈! 效果圖 這里展示了, 組合用幾個布局寫一個卡片 ( 好吧,好像好多文章都是寫卡片 ) 先上效果圖 代碼...

    SwiftUI實戰二:組合視圖和地圖視圖

    系統: Mac OS 10.15.1, XCode 11.2.1,swift 5.0 寫作時間:2019-11-29 說明 此例子包含元素:縱向組合容器VStack, 橫向組合容器HStack,UIImage,Map。這個項目的表達的意思是,地圖給出一個經緯度地標,顯示圖文介紹。 細節請查看官網教程 創建工程 工程名字:CreatingAndCombiningViews User Interfac...

    SwiftUI JSON文件下載、存儲、解析和展示(代碼大全)

    JSON 簡介 JSON(JavaScript Object Notation, JS 對象簡譜) 是一種輕量級的數據交換格式。它基于 ECMAScript (歐洲計算機協會制定的js規范)的一個子集,采用完全獨立于編程語言的文本格式來存儲和表示數據。簡潔和清晰的層次結構使得 JSON 成為理想的數據交換語言。 易于人閱讀和編寫,同時也易于機器解析和生成,并有效地提升網絡傳輸效率。 我們通常從服務...

    猜你喜歡

    SwiftUI 基礎之05 list 和 searchbar (2020)

    SwiftUI 基礎之05 list 和 searchbar (2020) 首要 searchbar 效果圖 image.png 參考資料 https://medium.com/better-programming/implement-searchbar-in-swiftui-556a204e1970...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    精品国产乱码久久久久久蜜桃不卡