SwiftUI — Data Flow Through SwiftUI

這一次我們來介紹一下 SwiftUI 里的屬性裝飾器@State, @Binding,@EnvironmentObject

@States

@frozen @propertyWrapper public struct State<Value> : DynamicProperty {

    /// Initialize with the provided initial value.
    public init(wrappedValue value: Value)

    /// Initialize with the provided initial value.
    public init(initialValue value: Value)

    /// The current state value.
    public var wrappedValue: Value { get nonmutating set }

    /// Produces the binding referencing this state value
    public var projectedValue: Binding<Value> { get }
}

@propertyWrapper 標(biāo)注和之前提到的 的 @_functionBuilder類似 例如下面@State修飾的代碼等同于 var showDetail = State(initialValue: false)侣背,會把使用過@State修飾器的屬性存儲到self上瞒滴,但是這個屬性和 View struct 是隔離的. 當(dāng)@State裝飾過的屬性發(fā)生了變化重抖,SwiftUI 會根據(jù)新的屬性值更新視圖

struct ContentView: View {
    @State  var showFavoritesOnly: Bool = false
    //var showDetail = State(initialValue: false)
    var body: some View {
        VStack{
          Button(action: {
                self.showFavoritesOnly.toggle()
            }) {
                Text("Change")
            }
            if showFavoritesOnly {
                Text("showFavoritesOnly")
            }else{
                Text("showAll)
            }
        }
    }
}

@Binding

上面例子是showDetail這個屬性 button 不會自動修改,但有些控件是可以直接修改埋心,就可以把一個視圖的屬性傳至控件中鹤竭,例如下面DetailView里面的Toggle就可以挂脑,但是又不能直接的傳遞給控件藕漱,因為在 Swift 中值的傳遞形式是值類型傳遞方式,也就是傳遞出去的是一個拷貝過的值崭闲。但是通過 @Binding 修飾器修飾后肋联,用$也等同于@Binding,屬性變成了一個引用類型刁俭,傳遞變成了引用傳遞橄仍,這樣父子視圖的狀態(tài)就能關(guān)聯(lián)起來了。

struct ContentView: View {
    @State  var isFavorite: Bool
    var body: some View {
        VStack{
          /// The binding value, as "unwrapped" by accessing `$foo` on a `@Binding` property.
           DetailView(isFavorite: $isFavorite)
            if isFavorite {
                Text("isFavorite")
            }else{
                Text("NoFavorite")
            }
        }
    }
}

struct DetailView: View {
    @Binding var isFavorite: Bool
    var body: some View {
        Toggle(isOn: $isFavorite) {
            Text("Change Favorite")
        }
    }
}

在 DetailView 視圖里用 @Binding 修飾 isFavorite 屬性, 在傳遞屬性是使用 $ 來傳遞 isFavorite 屬性的引用牍戚,這樣 DetailView 視圖就能讀寫父視圖 ContentView 里的狀態(tài)值了侮繁,并且值發(fā)生了修改 SwiftUI 會更新 ContentView 和 DetailView 視圖

@EnvironmentObject

從名字上可以看出,這個修飾器是針對全局環(huán)境的如孝。通過它宪哩,我們可以避免在初始 View 時創(chuàng)建 ObservableObject, 而是從環(huán)境中獲取 ObservableObject

@Environment

SwiftUI 本身就有很多系統(tǒng)默認(rèn)設(shè)定,我們可以使用@Environment 來獲取到它們

@Environment(.editMode) var mode
@Environment(.calendar) var calendar: Calendar
@Environment(.locale) var locale: Locale
@Environment(.colorScheme) var colorScheme: ColorScheme

使用系統(tǒng)的還可以得到很多好處第晰,例如你使用EditMode 就可以利用下面這些屬性來完成一個編輯頁面

public enum EditMode {

    /// The view content cannot be edited.
    case inactive

    /// The view is in a temporary edit mode.
    ///
    /// The definition of temporary might vary by platform or specific control.
    /// As an example, temporary edit mode may be engaged over the duration of
    /// a swipe gesture.
    case transient

    /// The view content can be edited.
    case active

    /// Indicates whether a view is being edited.
    public var isEditing: Bool { get }

    /// Returns a Boolean value indicating whether two values are equal.
    ///
    /// Equality is the inverse of inequality. For any values `a` and `b`,
    /// `a == b` implies that `a != b` is `false`.
    ///
    /// - Parameters:
    ///   - lhs: A value to compare.
    ///   - rhs: Another value to compare.

}

你可以監(jiān)聽各種狀態(tài)

import SwiftUI

struct ProfileHost: View {

    @Environment(\.editMode) var mode

    @State var draftProfile = Profile.default

    @EnvironmentObject var userData: UserData

    var body: some View {
          VStack(alignment: .leading, spacing: 20) {
                HStack {
                    if self.mode?.wrappedValue == .active {
                    Button("Cancel") {
                        self.draftProfile = self.userData.profile
                        self.mode?.animation().wrappedValue = .inactive
                        }
                    }
                    Spacer()
                    EditButton()
                }
            //
            if self.mode?.wrappedValue == .inactive {
                ProfileSummary(profile: draftProfile)
            } else {
                ProfileEditor(profile: $draftProfile)
                .onAppear {
                self.draftProfile = self.userData.profile
                }
                .onDisappear {
                self.userData.profile = self.draftProfile
             }
            }
        }
              .padding()
    }
}

struct ProfileHost_Previews: PreviewProvider {
    static var previews: some View {
        ProfileHost()
    }
}

上述代碼來自蘋果教程 Working with UI Controls

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锁孟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茁瘦,更是在濱河造成了極大的恐慌品抽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甜熔,死亡現(xiàn)場離奇詭異圆恤,居然都是意外死亡,警方通過查閱死者的電腦和手機腔稀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門哑了,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赘方,“玉大人,你說我怎么就攤上這事弱左≌福” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵拆火,是天一觀的道長跳夭。 經(jīng)常有香客問我,道長们镜,這世上最難降的妖魔是什么币叹? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮模狭,結(jié)果婚禮上颈抚,老公的妹妹穿的比我還像新娘。我一直安慰自己嚼鹉,他們只是感情好贩汉,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锚赤,像睡著了一般匹舞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上线脚,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天赐稽,我揣著相機與錄音,去河邊找鬼浑侥。 笑死姊舵,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的寓落。 我是一名探鬼主播蠢莺,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼零如!你這毒婦竟也來了躏将?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤考蕾,失蹤者是張志新(化名)和其女友劉穎祸憋,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肖卧,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蚯窥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拦赠。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡巍沙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出荷鼠,到底是詐尸還是另有隱情句携,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布允乐,位于F島的核電站矮嫉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏牍疏。R本人自食惡果不足惜蠢笋,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鳞陨。 院中可真熱鬧昨寞,春花似錦、人聲如沸厦滤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽馁害。三九已至,卻和暖如春蹂匹,著一層夾襖步出監(jiān)牢的瞬間碘菜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工限寞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忍啸,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓履植,卻偏偏與公主長得像计雌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子玫霎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

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