@State
通過使用 @State 修飾器我們可以關(guān)聯(lián)出 View 的狀態(tài). SwiftUI 將會把使用過 @State修飾器的屬性存儲到一個特殊的內(nèi)存區(qū)域双戳,并且這個區(qū)域和 View struct 是隔離的. 當(dāng) @State裝飾過的屬性發(fā)生了變化虹蒋,SwiftUI 會根據(jù)新的屬性值重新創(chuàng)建視圖
@Binding
有時候我們會把一個視圖的屬性傳至子節(jié)點中,但是又不能直接的傳遞給子節(jié)點飒货,因為在 Swift 中值的傳遞形式是值類型傳遞方式魄衅,也就是傳遞給子節(jié)點的是一個拷貝過的值。但是通過 @Binding 修飾器修飾后塘辅,屬性變成了一個引用類型晃虫,傳遞變成了引用傳遞,這樣父子視圖的狀態(tài)就能關(guān)聯(lián)起來了扣墩。
struct ContentView: View{
? ? @State private var num:Int = 0;?
? ? var body: some View{
? ? ? ? VStack{
? ? ? ? ? ? Button("數(shù)字+1:\(num)")
? ? ? ? ? ? {
? ? ? ? ? ? ? ? self.num += 1;
? ? ? ? ? ? }
? ? ? ? ? ? SubView(subCounter:$num)
? ? ? ? }
? ? }
}
struct SubView: View{
? ? @Binding var subCounter:Int
? ? var body: some View{
? ? ? ? VStack{
? ? ? ? ? ? Text("計數(shù):\(subCounter)")
? ? ? ? ? ? Button("數(shù)字加一:\(subCounter)")
? ? ? ? ? ? {
? ? ? ? ? ? ? ? self.subCounter += 1;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
@ObservedObject
@ObservedObject 的用處和 @State 非常相似哲银,從名字看來它是來修飾一個對象的,這個對象可以給多個獨立的 View使用呻惕。如果你用 @ObservedObject 來修飾一個對象盘榨,那么那個對象必須要實現(xiàn) ObservableObject 協(xié)議,然后用@Published 修飾對象里屬性蟆融,表示這個屬性是需要被 SwiftUI 監(jiān)聽的
import Combine
final class PodcastPlayer: ObservableObject {
? ? @Published private(set) var isPlaying: Bool = false
? ? func play() {
? ? ? ? isPlaying = true
? ? }
? ? func pause() {
? ? ? ? isPlaying = false
? ? }
}
這里定義了一個 PodcastPlayer 類草巡,這個類可以給不同的 View 使用,SwiftUI 會追蹤使用 View 里經(jīng)過@ObservableObject修飾過的對象里進(jìn)過 @Published 修飾的屬性變換,一旦發(fā)生了變換山憨,SwiftUI 會更新相關(guān)聯(lián)的 UI
struct EpisodesView: View {
? ? @ObservedObject var player: PodcastPlayer
? ? let episodes: [Episode]
? ? var body: some View {
? ? ? ? List {
? ? ? ? ? ? Button(
? ? ? ? ? ? ? ? action: {
? ? ? ? ? ? ? ? ? ? if self.player.isPlaying {
? ? ? ? ? ? ? ? ? ? ? ? self.player.pause()
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? self.player.play()
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? }, label: {
? ? ? ? ? ? ? ? ? ? Text(player.isPlaying ? "Pause": "Play")
? ? ? ? ? ? ? ? }
? ? ? ? ? ? )
? ? ? ? ? ? ForEach(episodes) { episode in
? ? ? ? ? ? ? ? Text(episode.title)
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
@EnvironmentObject
從名字上可以看出查乒,這個修飾器是針對全局環(huán)境的。通過它郁竟,我們可以避免在初始 View 時創(chuàng)建 ObservableObject, 而是從環(huán)境中獲取 ObservableObject
@Environment
SwiftUI 本身就有很多系統(tǒng)級別的設(shè)定玛迄,我們開一個通過@Environment來獲取到它們
struct CalendarView: View {
? ? @Environment(\.calendar) var calendar: Calendar
? ? @Environment(\.locale) var locale: Locale
? ? @Environment(\.colorScheme) var colorScheme: ColorScheme
? ? var body: some View {
? ? ? ? return Text(locale.identifier)
? ? }
}
通過@Environment修飾的屬性,我們開一個監(jiān)聽系統(tǒng)級別信息的變換棚亩,這個例子里一旦Calendar, Locale, ColorScheme發(fā)生了變換蓖议,我們定義的 CalendarView 就會刷新.