SwiftUI 屬性包裝器(property wrappers)

包裝屬性包裝器(Wrapping up property wrappers)

使用屬性包裝器(property wrappers)疯趟,我們需要注意管理的是值的狀態(tài)還是對(duì)象的狀態(tài)沸移。值主要用于描述 app 用戶界面的狀態(tài)环疼。如果我們可以使用值數(shù)據(jù)類(lèi)型對(duì) app 的數(shù)據(jù)進(jìn)行建模,那么很幸運(yùn)在讶,因?yàn)槲覀冇懈嘤糜谔幚碇档膶傩园b器選項(xiàng)蟀伸。 但在某種程度上泌类,大多數(shù) app 需要引用類(lèi)型來(lái)對(duì)其數(shù)據(jù)進(jìn)行建模,通常用于在集合中添加或刪除項(xiàng)目藤滥。

包裝值類(lèi)型(Wrapping values)

@State 和 @Binding 是值屬性包裝器的主力鳖粟。如果視圖沒(méi)有從任何父視圖接收到值,則視圖擁有該值拙绊。在這種情況下向图,它是一個(gè) @State 屬性——唯一的事實(shí)來(lái)源(source of truth)泳秀。首次創(chuàng)建視圖時(shí),它會(huì)初始化其 @State 屬性榄攀。當(dāng) @State 值改變時(shí)嗜傅,視圖會(huì)重繪自身,重置除 @State 屬性之外的所有內(nèi)容檩赢。

擁有@State 屬性的視圖可以將 @State 值作為普通只讀值或作為讀寫(xiě) @Binding 傳遞給子視圖吕嘀。

當(dāng)我們?yōu)?app 制作原型并嘗試子視圖時(shí),可能會(huì)將其編寫(xiě)為僅具有 @State 屬性的獨(dú)立視圖贞瞒。稍后偶房,當(dāng)將其放入 app 時(shí),我們只需將來(lái)自父視圖的值屬性的 @State 更改為 @Binding军浆。

我們的 app 可以訪問(wèn)內(nèi)置的 @Environment 值棕洋。環(huán)境值保留在我們附加的視圖的子樹(shù)中。通常瘾敢,這只是像 VStack 這樣的容器拍冠,我們可以在其中使用環(huán)境值來(lái)設(shè)置默認(rèn)值,如字體大小簇抵。

注意:我們還可以定義自己的自定義環(huán)境值庆杜,例如將視圖的屬性公開(kāi)給祖先視圖。

我們可以在 @AppStorage 或 @SceneStorage 字典中存儲(chǔ)一些值碟摆。@AppStorage 值在 UserDefaults 中晃财,因此它們?cè)?app 關(guān)閉后仍然存在。當(dāng)應(yīng)用重新打開(kāi)時(shí)典蜕,我們可以使用 @SceneStorage 值來(lái)恢復(fù)場(chǎng)景的狀態(tài)断盛。在 iOS 中,場(chǎng)景最容易被視為 iPad 上的多個(gè)窗口愉舔。

包裝引用類(lèi)型(Wrapping objects)

當(dāng)我們的 app 需要更改并響應(yīng)引用類(lèi)型的更改時(shí)钢猛,我們創(chuàng)建一個(gè)符合 ObservableObject 并發(fā)布適當(dāng)屬性的類(lèi)。在這種情況下轩缤,使用 @StateObject 和 @ObservedObject 的方式與 @State 和 @Binding 用于值的方式非常相似命迈。

我們將視圖中的發(fā)布者類(lèi)實(shí)例化為 @StateObject,然后將其作為 @ObservedObject 傳遞給子視圖火的。當(dāng)擁有視圖(the owning view)重繪自身時(shí)壶愤,它不會(huì)重置其 @StateObject 屬性。

如果我們的 app 的視圖需要更靈活地訪問(wèn)對(duì)象馏鹤,則可以將其提升到視圖子樹(shù)的環(huán)境(environment)中征椒,讓其類(lèi)型仍然是 @StateObject。我們必須在此處實(shí)例化它湃累。如果忘記創(chuàng)建它勃救,app 將會(huì)崩潰碍讨。然后使用 .environmentObject(_:) 修飾符將其附加到視圖。視圖子樹(shù)中的任何視圖都可以通過(guò)聲明該類(lèi)型的 @EnvironmentObject 來(lái)訂閱發(fā)布者對(duì)象剪芥。

要使 app 中的每個(gè)視圖都可以使用環(huán)境(environment)對(duì)象垄开,可以在 app 創(chuàng)建其 WindowGroup 時(shí)將其附加到根視圖。

@ViewBuilder

各種內(nèi)置視圖税肪,例如 HStack 和 VStack 通過(guò)使用 @ViewBuilder 可以顯示各種類(lèi)型的視圖溉躲。

擁有 @State 屬性的視圖可以將其值或綁定(binding)傳遞給其子視圖。如果它將綁定傳遞給子視圖益兄,則該子視圖就具有了對(duì)事實(shí)源(the source of truth)的引用锻梳。 這允許它更新該屬性的值或在該值更改時(shí)重繪自身。當(dāng) @State 值發(fā)生變化時(shí)净捅,任何引用它的視圖都會(huì)使其外觀無(wú)效并重繪自身以顯示新?tīng)顟B(tài)疑枯。

視圖是一種結(jié)構(gòu)體,因此除非將其包裝為 @State 或 @Binding 屬性蛔六,否則我們無(wú)法更改其屬性值荆永。

// 有時(shí)候我們會(huì)把一個(gè)視圖的屬性傳至子節(jié)點(diǎn)中,
// 但是又不能直接的傳遞給子節(jié)點(diǎn)国章,因?yàn)樵?Swift 中值的傳遞形式是值類(lèi)型傳遞方式具钥,
// 也就是傳遞給子節(jié)點(diǎn)的是一個(gè)拷貝過(guò)的值。
// 但是通過(guò) @Binding 修飾器修飾后液兽,屬性變成了一個(gè)引用類(lèi)型骂删,傳遞變成了引用傳遞,
// 這樣父子視圖的狀態(tài)就能關(guān)聯(lián)起來(lái)了四啰。
  @Binding var selected: Set<String>

擁有@State 屬性的視圖負(fù)責(zé)初始化它宁玫。 @State 屬性包裝器為視圖結(jié)構(gòu)體之外的值創(chuàng)建持久存儲(chǔ),并在視圖重繪自身時(shí)保留其值柑晒。這意味著初始化只發(fā)生一次欧瘪。

如果 是一個(gè)類(lèi),而不是一個(gè)結(jié)構(gòu)體匙赞,則不能使用 @State 屬性包裝器恋追,應(yīng)該使用@StateObject。

@StateObject 屬性包裝器確保一個(gè)類(lèi)僅被實(shí)例化一次罚屋。 當(dāng) ContentView 重繪自身時(shí),它仍然存在嗅绸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末脾猛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鱼鸠,更是在濱河造成了極大的恐慌猛拴,老刑警劉巖羹铅,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異愉昆,居然都是意外死亡职员,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)跛溉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)焊切,“玉大人,你說(shuō)我怎么就攤上這事芳室∽ǚ荆” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵堪侯,是天一觀的道長(zhǎng)嚎尤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)伍宦,這世上最難降的妖魔是什么芽死? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮次洼,結(jié)果婚禮上关贵,老公的妹妹穿的比我還像新娘。我一直安慰自己滓玖,他們只是感情好坪哄,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著势篡,像睡著了一般翩肌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上禁悠,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天念祭,我揣著相機(jī)與錄音,去河邊找鬼碍侦。 笑死粱坤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瓷产。 我是一名探鬼主播站玄,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼濒旦!你這毒婦竟也來(lái)了株旷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晾剖,沒(méi)想到半個(gè)月后锉矢,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡齿尽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年沽损,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片循头。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绵估,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贷岸,到底是詐尸還是另有隱情壹士,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布偿警,位于F島的核電站躏救,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏螟蒸。R本人自食惡果不足惜盒使,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望七嫌。 院中可真熱鬧少办,春花似錦、人聲如沸诵原。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绍赛。三九已至蔓纠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吗蚌,已是汗流浹背腿倚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚯妇,地道東北人敷燎。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像箩言,于是被迫代替她去往敵國(guó)和親硬贯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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