新聞中心
概覽
如果視圖需要數(shù)據(jù)來確定各視圖間共享的單一數(shù)據(jù)源,則可以在視圖最不常見的上級(jí)結(jié)構(gòu)中將數(shù)據(jù)存儲(chǔ)為狀態(tài)。既可通過一個(gè) Swift 屬性以只讀方式提供這個(gè)數(shù)據(jù),也可使用綁定創(chuàng)建與狀態(tài)的雙向連接。SwiftUI 會(huì)觀察數(shù)據(jù)的變化,并根據(jù)需要更新任何受影響的視圖。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名與空間、虛擬主機(jī)、營(yíng)銷軟件、網(wǎng)站建設(shè)、增城網(wǎng)站維護(hù)、網(wǎng)站推廣。
請(qǐng)勿將狀態(tài)屬性用于持久存儲(chǔ),因?yàn)闋顟B(tài)變量的生命周期與視圖生命周期是一樣的。應(yīng)將它們用于管理僅影響用戶界面的瞬間狀態(tài),例如按鈕的高亮顯示狀態(tài)、篩選器設(shè)置或當(dāng)前選定的列表項(xiàng)目。你可能還會(huì)發(fā)現(xiàn),在你準(zhǔn)備對(duì) App 數(shù)據(jù)模型進(jìn)行更改之前制作原型時(shí),這種存儲(chǔ)很方便。
將可變值作為狀態(tài)來管理
如果視圖需要儲(chǔ)存它可以修改的數(shù)據(jù),應(yīng)通過 State (英文) 屬性包裝器聲明一個(gè)變量。例如,你可以在播客播放器視圖中創(chuàng)建一個(gè) isPlaying Boolean,以跟蹤播客何時(shí)運(yùn)行:
struct PlayerView: View { @State private var isPlaying: Bool = false var body: some View { // ... } }
將屬性標(biāo)記為狀態(tài)會(huì)指示框架管理底層存儲(chǔ)。你的視圖使用屬性名稱,讀取和寫入在狀態(tài)的 wrappedValue (英文) 屬性中找到的數(shù)據(jù)。在你更改值時(shí),SwiftUI 會(huì)更新視圖的受影響部分。例如,你可以向 PlayerView 添加一個(gè)按鈕,在輕點(diǎn)該按鈕后切換存儲(chǔ)的值并根據(jù)存儲(chǔ)的值顯示不同的圖像:
Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") }
通過將狀態(tài)變量聲明為私有變量來限制它們的范圍。這確保變量在聲明它們的視圖層次結(jié)構(gòu)中保持封裝狀態(tài)。
聲明 Swift 屬性以存儲(chǔ)不可變值
若要為視圖提供其不修改的數(shù)據(jù),請(qǐng)聲明一個(gè)標(biāo)準(zhǔn) Swift 屬性。例如,你可以擴(kuò)展播客播放器,以增加一個(gè)輸入結(jié)構(gòu),用于包含代表單集標(biāo)題和節(jié)目名稱的字符串:
struct PlayerView: View { let episode: Episode // The queued episode. @State private var isPlaying: Bool = false var body: some View { VStack { // Display information about the episode. Text(episode.title) Text(episode.showTitle) Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }
盡管單集屬性的值對(duì)于 PlayerView 是一個(gè)常量,但在這個(gè)視圖的父視圖中,它不一定要是常量。當(dāng)用戶在父項(xiàng)中選擇另一個(gè)單集時(shí),SwiftUI 會(huì)檢測(cè)到狀態(tài)變化并使用一個(gè)新輸入來重新創(chuàng)建 PlayerView。
通過綁定共享狀態(tài)訪問
如果視圖需要與一個(gè)子視圖共享狀態(tài)的控件,應(yīng)在帶有 Binding (英文) 屬性包裝器的子項(xiàng)中聲明一個(gè)屬性。綁定表示對(duì)現(xiàn)有存儲(chǔ)的引用,從而保留底層數(shù)據(jù)的單一數(shù)據(jù)源。例如,如果你將播客播放器視圖的按鈕重構(gòu)成一個(gè)名為 PlayButton 的子視圖,你可以給它提供一個(gè)與 isPlaying 屬性的綁定:
struct PlayButton: View { @Binding var isPlaying: Bool var body: some View { Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }
如上所示,你可以通過直接引用屬性來讀取和寫入綁定包裝的值,這一點(diǎn)與狀態(tài)屬性一樣。但是與狀態(tài)屬性不同的是,綁定沒有自己的存儲(chǔ),而是引用一個(gè)存儲(chǔ)在其他地方的狀態(tài)屬性,并提供與該存儲(chǔ)的雙向連接。
當(dāng)你實(shí)例化 PlayButton 時(shí),可通過添加一個(gè)美元符號(hào) ($) 前綴,提供與父視圖中聲明的相應(yīng)狀態(tài)變量的綁定:
struct PlayerView: View { var episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title) Text(episode.showTitle) PlayButton(isPlaying: $isPlaying) // Pass a binding. } } }
$ 前綴要求為它的 projectedValue (英文) 提供一個(gè)包裝的屬性,這對(duì)狀態(tài)而言,就是與底層存儲(chǔ)的綁定。同樣,你可以通過使用 $ 前綴的綁定獲得綁定,從而讓你可以在視圖層次結(jié)構(gòu)的任意數(shù)量層級(jí)間傳遞綁定。
你還可以獲得與狀態(tài)變量中限定范圍的值的綁定。例如,如果你在播放器的父視圖中將 episode 聲明為狀態(tài)變量,并且單集結(jié)構(gòu)還包含一個(gè)你想要通過切換控制的 isFavorite Boolean,那么,你可以引用 $episode.isFavorite 來獲得與單集的個(gè)人收藏狀態(tài)的綁定:
struct Podcaster: View { @State private var episode = Episode(title: "Some Episode", showTitle: "Great Show", isFavorite: false) var body: some View { VStack { Toggle("Favorite", isOn: $episode.isFavorite) // Bind to the Boolean. PlayerView(episode: episode) } } }
為狀態(tài)過渡添加動(dòng)畫效果
當(dāng)視圖狀態(tài)發(fā)生改變時(shí),SwiftUI 會(huì)立即更新受影響的視圖。如果你需要實(shí)現(xiàn)順暢的視覺過渡,可以將觸發(fā)過渡的狀態(tài)更改包裝在對(duì) withAnimation(_:_:) (英文) 函數(shù)的調(diào)用中,以指示 SwiftUI 為它們添加動(dòng)畫效果。例如,你可以為由 isPlaying Boolean 控制的更改添加動(dòng)畫效果:
withAnimation(.easeInOut(duration: 1)) { self.isPlaying.toggle() }
通過更改動(dòng)畫函數(shù)結(jié)尾閉包中的 isPlaying,可指示 SwiftUI 為依賴于包裝值的一切內(nèi)容添加動(dòng)畫效果,例如,按鈕圖像上的縮放特效:
Image(systemName: isPlaying ? "pause.circle" : "play.circle") .scaleEffect(isPlaying ? 1 : 1.5)
SwiftUI 會(huì)使用你指定的曲線和持續(xù)時(shí)間,如果你未提供則使用合理的默認(rèn)值,在一段時(shí)間內(nèi)在給定的 1 和 1.5 值之間過渡縮放特效輸入。另一方面,圖像內(nèi)容不會(huì)受到動(dòng)畫的影響,即使同一個(gè) Boolean 規(guī)定要顯示哪個(gè)系統(tǒng)圖像也是如此。那是因?yàn)?SwiftUI 無法以有意義的方式在兩個(gè)字符串 pause.circle 和 play.circle 之間逐步過渡。
你可以向狀態(tài)屬性添加動(dòng)畫,或與上述示例一樣,向綁定添加動(dòng)畫。無論是哪一種方式,在底層存儲(chǔ)的值發(fā)生變化時(shí),SwiftUI 都會(huì)為發(fā)生的任何視圖變化添加動(dòng)畫效果。例如,如果你在動(dòng)畫塊位置上方的某個(gè)視圖層次結(jié)構(gòu)層級(jí)向 PlayerView 添加背景色,SwiftUI 同樣會(huì)為此添加動(dòng)畫效果:
VStack { Text(episode.title) Text(episode.showTitle) PlayButton(isPlaying: $isPlaying) } .background(isPlaying ? Color.green : Color.red) // Transitions with animation.
如果你想將動(dòng)畫應(yīng)用于特定的視圖,而不是狀態(tài)變化觸發(fā)的所有視圖,請(qǐng)改用 animation(_:) (英文) 視圖修飾符。
本文名稱:創(chuàng)新互聯(lián)IOS教程:管理用戶界面狀態(tài)
路徑分享:http://fisionsoft.com.cn/article/dpdpdps.html


咨詢
建站咨詢
