SwiftUI一起學(xué)之二 -- SwiftUI的狀態(tài)管理

一 @State

加了@State注解的變量,視圖通過監(jiān)視和讀取該變量來重新渲染UI缺虐。

struct NextPageView: View {
    // State針對具體View的內(nèi)部變量進行管理,不應(yīng)該從外部被允許訪問礁凡,所以應(yīng)該標記為private
    @State private var count:Int = 0;
    @State private var name:String = "";
    
    var body: some View {
        VStack{
            Text("數(shù)量 = \(count)")
            Button("數(shù)量+1"){
                count = count+1
            }
            // 只讀直接使用變量名即可
            Text("你的名字 = \(name)")
            // 如果是讀寫都有高氮,引用屬性需要$開頭
            TextField("請輸入你的名字", text: $name)
        }
    }
}
image.png
image.png

二 @Published

@Published是SwiftUI最有用的包裝之一慧妄,允許我們創(chuàng)建出能夠被自動觀察的對象屬性,SwiftUI會自動監(jiān)視這個屬性剪芍,一旦發(fā)生了改變塞淹,會自動修改與該屬性綁定的界面。

三 @ObservedObject

@ObservedObject告訴SwiftUI罪裹,這個對象是可以被觀察的饱普,里面含有被@Published包裝了的屬性。
@ObservedObject包裝的對象状共,必須遵循ObservableObject協(xié)議套耕。也就是說必須是class對象,不能是struct峡继。
@ObservedObject允許外部進行訪問和修改冯袍。

class DataViewModel: ObservableObject {
    @Published  var value: Int = 0
    init() {
        for i in 1...10 {
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(i)) {
                self.value += 1
            }
        }
     }
}

struct NextPageView: View {
    @ObservedObject var viewModel = DataViewModel()

    var param:String 
    var body: some View {
        VStack{
            // viewModel的數(shù)據(jù)變化將自動更新view
            Text("數(shù)量 = \(viewModel.value)")
            Spacer()
        }
    }
}
image.png
image.png

四 @EnvironmentObject

@State處理單個視圖的局部狀態(tài),以及@ObservedObject如何使我們在視圖之間傳遞一個對象碾牌,以便我們可以共享它康愤,@ EnvironmentObject更進一步:我們可以將對象放置到環(huán)境中,以便任何子視圖都可以自動訪問它舶吗。
@EnvironmentObject包裝的屬性是全局的翘瓮,整個app都可以訪問

class User: ObservableObject {
    @Published var name = "Sunny"
}

struct EnvironmentObjectView: View {
    let user = User()

    var body: some View {
        VStack {
            EditView().environmentObject(user)
            DisplayView().environmentObject(user)
        }
    }
}

struct EditView: View {
    @EnvironmentObject var user: User

    var body: some View {
        TextField("Name", text: $user.name)
    }
}

struct DisplayView: View {
    @EnvironmentObject var user: User

    var body: some View {
        Text(user.name)
    }
}

五 @Environment

@Environment與@EnvironmentObject作用是不同的,@Environment是從環(huán)境中取出預(yù)定義的值裤翩,比如獲得當(dāng)前是暗黑模式還是正常模式资盅,屏幕的大小等等。
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.managedObjectContext) var managedObjectContext

根據(jù) Light 和 Dark 兩種系統(tǒng)顏色模式來調(diào)整 app 界面的配色是很常見的需求踊赠。方法很簡單呵扛,通過 Environment.colorScheme 獲取當(dāng)前系統(tǒng)環(huán)境的顏色方案就行了:

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

六 @Binding

把一個視圖的屬性傳至子節(jié)點中,但是又不能直接的傳遞給子節(jié)點筐带,因為在 Swift 中值的傳遞形式是值類型傳遞方式今穿,也就是傳遞給子節(jié)點的是一個拷貝過的值。但是通過 @Binding 修飾器修飾后伦籍,屬性變成了一個引用類型蓝晒,傳遞變成了引用傳遞,這樣父子視圖的狀態(tài)就能關(guān)聯(lián)起來了.

struct NextPageView: View {
    // State針對具體View的內(nèi)部變量進行管理帖鸦,不應(yīng)該從外部被允許訪問芝薇,所以應(yīng)該標記為private
    @State private var count:Int = 0;
    @State private var name:String = "";
    var param:String 
    
    var body: some View {
        VStack{
            Text("數(shù)量 = \(count)")
            Button("數(shù)量+1"){
                count = count+1
            }
            // 只讀直接使用變量名即可
            Text("你的名字 = \(name)")
            // 如果是讀寫都有,引用屬性需要$開頭
            TextField("請輸入你的名字", text: $name)
            // 子節(jié)點傳遞
            ChildView(name: $name)
            Spacer()
        }
    }
}

struct ChildView: View {
    // 通過@Binding子節(jié)點的修改,會變更到父節(jié)點上
    @Binding var name: String
//    @State var name: String
    var body: some View {
        VStack{
            Text("子節(jié)點獲取名字 : \(name)")
            TextField("子節(jié)點請輸入你的名字", text: $name)
        }
    }
}
image.png
image.png

七 @GestureState

@GestureState能夠讓我們傳遞手勢的狀態(tài)作儿,雖然使用@State也能實現(xiàn)洛二,但@GestureState能讓手勢結(jié)束后我們回到最初的狀態(tài)。

struct GesturesUIView: View {
    @GestureState var isLongPressed = false
    
    var body: some View {
        let longPress = LongPressGesture()
            .updating($isLongPressed) { value,state,transcation in
                print(value)
                state = value
            }
        
        return Rectangle()
            .fill(isLongPressed ? Color.red: Color.green)
            .frame(width: 300, height: 300)
            .cornerRadius(8)
            .padding()
            .scaleEffect(isLongPressed ? 1.2 : 1)
            .gesture(longPress)
            .animation(.interactiveSpring())
    }
}
image.png
image.png

參考:

  1. @StateObject 和 @ObservedObject 的區(qū)別和使用
  2. SwiftUI 探索 - 狀態(tài)和數(shù)據(jù)流
  3. SwiftUI數(shù)據(jù)流與界面綁定
  4. SwiftUI內(nèi)功之Environment深入研究與使用
  5. SwiftUI 關(guān)鍵詞解析
  6. SwiftUI數(shù)據(jù)流之State&Binding
  7. 【SwiftUI】手勢(Gestures)的使用
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市晾嘶,隨后出現(xiàn)的幾起案子妓雾,更是在濱河造成了極大的恐慌,老刑警劉巖垒迂,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件械姻,死亡現(xiàn)場離奇詭異,居然都是意外死亡机断,警方通過查閱死者的電腦和手機楷拳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毫缆,“玉大人唯竹,你說我怎么就攤上這事】喽。” “怎么了浸颓?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長旺拉。 經(jīng)常有香客問我产上,道長,這世上最難降的妖魔是什么蛾狗? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任晋涣,我火速辦了婚禮,結(jié)果婚禮上沉桌,老公的妹妹穿的比我還像新娘谢鹊。我一直安慰自己,他們只是感情好留凭,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布佃扼。 她就那樣靜靜地躺著,像睡著了一般蔼夜。 火紅的嫁衣襯著肌膚如雪兼耀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天求冷,我揣著相機與錄音瘤运,去河邊找鬼。 笑死匠题,一個胖子當(dāng)著我的面吹牛拯坟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梧躺,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼似谁,長吁一口氣:“原來是場噩夢啊……” “哼傲绣!你這毒婦竟也來了掠哥?” 一聲冷哼從身側(cè)響起巩踏,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎续搀,沒想到半個月后塞琼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡禁舷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年彪杉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牵咙。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡派近,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出洁桌,到底是詐尸還是另有隱情渴丸,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布另凌,位于F島的核電站谱轨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吠谢。R本人自食惡果不足惜土童,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望工坊。 院中可真熱鬧献汗,春花似錦、人聲如沸王污。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玉掸。三九已至刃麸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間司浪,已是汗流浹背泊业。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留啊易,地道東北人吁伺。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像租谈,于是被迫代替她去往敵國和親篮奄。 傳聞我的和親對象是個殘疾皇子捆愁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容