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"
}
}
}