SwiftUI狀態管理--Combine(Environment、EnvironmentObject)


SwiftUI 已經如同前端vue、react 一般支持響應式編程。也有類似前端的 state。如今swiftUI已經到2.0版本。swift 也已經5.5了 。所以現階段從OC 切換到swift是一個非常合適的時機(有點晚)。了解swift 或者前端就會明白OC的笨重。作為一個已經使用了8年OC的開發來說,切換到swift無疑有著不舍。不過學習新的東西,總是充滿了挑戰。

通過最近的學習和使用特此整理。本文以實際使用出發。具體實現原理待后面研究源碼再進行整理。
在實際項目中使用到的有:

  • AppStorage
  • Environment
  • EnvironmentObject
  • ObservedObject
  • StateObject

Environment

值類型,當創建應用時,會自動創建Environment。其主要作用是傳遞系統的一些設置。如ColorScheme、NSManagedObjectContext。系統又很多對應的key可以查看EnvironmentValues獲取key列表。
在需要使用的view中,只需要使用PropertyWrapper屬性包裝器 @Enviroment

import SwiftUI

struct HomePageView: View {
    // colorScheme values: .light, .dark
    @Enviroment(\.colorScheme) var colorScheme
    
    var body: some View {
        Text("Hello, World")
            .foregroundColor(colorScheme = .light ? .yellow : .blue)
    }
}

雖然系統自動創建,不過我們也可以自定義一個EnviromentKey,代碼如下:

import Foundation
import SwiftUI

struct UserInfo {
    var userName: String = ""
    init(userName: String) {
        self.userName = userName
    }
}

struct UserInfoKey: EnvironmentKey {
    static var defaultValue: UserInfo {
        return UserInfo(userName: "lixxx")
    }
}

extension EnvironmentValues {
    var userInfo: UserInfo {
        get { return self[UserInfoKey.self] }
        set { self[UserInfoKey] = newValue }
    }
}

在使用自定義的Environment時,要手動去注入到根視圖上。并初始化注入對象為其設置一個值。

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        TabbarPageView()
            .environment(\.userInfo, UserInfo(userName: "liqingyu"))
  
    }
}

EnvironmentObject

引用類型,和Environment作用相同,可操作性強,可以使用其為應用進行設置全局變量。共享數據于應用各個頁面。
首先創建一個全局對象。因為我們要使用這個對象,并且可能會進行修改,修改后可能會刷新界面等操作。所以我們要觀察這個對象 所以使用ObservableObject 協議 通過@Published 當值發生變化時通知全局作出響應。

import Foundation

class Person:ObservableObject {
    @Published var name = ""
}

在根視圖上進行注入,子視圖將可以進行響應

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        TabbarPageView()
            .environmentObject(Person())  
    }
}

在需要使用的試圖進行引入操作

import SwiftUI

struct EnvironmentPageView: View {
    @EnvironmentObject var person: Person
    var body: some View {
        VStack{
            Text("name: \(person.name)")
        }
    }
}

編輯操作,Binding值綁定 及 = 屬性設置都是可以的

import SwiftUI

struct EnvironmentDetailView: View {
    @EnvironmentObject var person: Person
    var body: some View {
        TextField("Person", text: $person.name)
            .padding(20)
        .navigationBarTitleDisplayMode(.inline)
         .onAppear(){
                person.name = "liqngyu"
            }
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯系作者。

推薦閱讀更多精彩內容

  • 一 @State 加了@State注解的變量,視圖通過監視和讀取該變量來重新渲染UI。 二 @Published ...
    sunny_ke_ke閱讀 2,347評論 0 10
  • 學習文章 文集:Hacking with iOS: SwiftUI Edition[https://www.jia...
    xmb閱讀 4,537評論 3 14
  • 最近抽空終于把官方SwiftUI Tutorials擼了一遍,網上已經很多翻譯或者該Tutorials說明。 這...
    JerrySi閱讀 1,592評論 0 0
  • NavigationView是SwiftUI應用的一個重要組件,它允許我們輕松地push和pop屏幕,以清晰、分層...
    豬豬行天下閱讀 11,698評論 1 9
  • SwiftUI要求 iOS13.0+ 快捷鍵 control + option + 點擊:出現屬性編輯器 comm...
    余青松閱讀 6,327評論 1 11