在 SwiftUI 官方教程中,Apple 時常提出“化整為零”的界面布局思想。簡單來說,Apple 推薦 SwiftUI 視圖的構建方式是:用若干自定義小視圖來構成上層的功能視圖。
這是為什么呢?
在本篇博文中,我們將用一個通俗易懂的示例來討論這樣做的重要原因。
無需等待,Let’s Go!
首先,從軟件工程的角度來說,用自定義視圖來代替原始布局代碼有利于封裝和代碼重用。
比如 SwiftUI 中需要在各個功能視圖頂部彈出 HUD 小視圖:
如果在每個功能視圖中都寫一遍 HUD 視圖代碼,之后一旦需要修改 HUD 實現,在所有父視圖中都需做出改動,這種“牽一發(fā)而動全身”的行為顯然不符合日后的代碼維護。
所以,這時把 HUD 的實現放在定制視圖中無疑是一個明智的選擇:
struct HUD: View {@ViewBuilder let content: Content
var body: some View {content
.padding(.horizontal, 12)
.padding(16)
.background(
Capsule()
.foregroundColor(Color.white)
.shadow(color: Color(.black).opacity(0.16), radius: 12, x: 0, y: 5)
)
}
}
現在,在所有功能視圖中我們都可以嵌入統一的 HUD 子視圖,避免了代碼重復:
1.2 自定義視圖有利于 SwiftUI 優(yōu)化界面刷新SwiftUI 非常聰明,當視圖對應的狀態(tài)發(fā)生變化時,它會及時的刷新狀態(tài)對應的內容。
不過在有些情況下, SwiftUI 仍然需要我們來為它提供“更優(yōu)化”的刷新建議。
具體來說:如果一個狀態(tài)對應的視圖界面被刷新,其中所有的視圖都會被刷新,盡管其中某些視圖實際上無需刷新(繞口令?)。
這時,若我們用自定義子視圖分割顯示邏輯代碼,且被更改的狀態(tài)沒有影響到該子視圖,則 SwiftUI 就不會刷新這些子視圖,從而有效的提高了視圖渲染性能。
有些童鞋可能擔心 SwiftUI 中將父視圖劃分為大量自定義子視圖會帶來顯示性能上的災難。
其實這種擔心是多慮了。
首先,SwiftUI 中視圖的實現非常輕量級,而且 Apple 對 SwiftUI 中整個視圖繼承體系的渲染在底層做了很好的優(yōu)化,嵌入大量子視圖一般不會顯著影響顯示性能。其次,如果確實有性能問題,我們隨時可以通過性能檢測工具來確定性能瓶頸點,再選擇優(yōu)化也不遲。
過早優(yōu)化是“萬惡之源”,切記切記!😉
2. 一個“栗子”也許大家對上面 “自定義視圖有利于 SwiftUI 優(yōu)化界面刷新” 這一概念仍不是太理解。
沒關系,下面我們就用一個簡單的例子讓小伙伴們直觀感受界面刷新優(yōu)化前后的差別。
extension ShapeStyle where Self == Color {static var random: Color {Color(
red: .random(in: 0...1),
green: .random(in: 0...1),
blue: .random(in: 0...1)
)
}
}
struct HyButtonStyle: ButtonStyle {func makeBody(configuration: Configuration) ->some View {configuration.label
.font(.title)
.padding()
.foregroundColor(.white)
.background(Color.gray)
.clipShape(RoundedRectangle(cornerRadius: 10))
}
}
struct ContentView: View {@State var s_one = 0
@State var s_two = 0
var body: some View {NavigationStack {VStack(spacing: 50.0) {Text("one: \(s_one)")
HStack {Text("two: \(s_two)")
}
.padding()
.background(Color.random)
HStack(spacing: 50) {Button("add one"){s_one += 1
}.buttonStyle(HyButtonStyle())
Button("add two"){s_two += 1
}.buttonStyle(HyButtonStyle())
}
}
.font(.title2)
.padding()
.background(Color.random)
.navigationTitle("視圖“冗余”刷新演示")
}
}
}
順面說一下,上述代碼利用了
SwiftUI 如何快速識別視圖(View)界面的刷新是由哪個狀態(tài)的改變導致的? 博文中的調試技術。
簡單來說,當視圖被刷新時其背景色也會發(fā)生變化,我們可以用肉眼輕易辨別出每個視圖是否被刷新了。
上面是一段非常簡單的代碼,按道理來說,狀態(tài) s_one 只會影響父視圖中的 Text("one: ") 文本,而 s_two 只會影響 Text("two: ") 文本。但實際上它們會互相影響:
如上圖所示:改變 s_one 會刷新 Text("two: "),而改變 s_two 同樣也會強制不相干 Text("one: ") 視圖的刷新(觀察它們背景色的變化)。
下面,我們將 Text("two: ") 包裝到自定義的子視圖 HySubView 中去:
struct HySubView: View {@Binding var val: Int
var body: some View {HStack {Text("s_two: \(val)")
}
.padding()
.background(Color.random)
}
}
將 ContentView 中原內容替換為 HySubView:
VStack(spacing: 50.0) {Text("one: \(s_one)")
HySubView(val: $s_two)
// 其它代碼從略...
}
現在,我們再來看看更改 s_one 和 s_two 狀態(tài)對它們的影響:
可以看到,現在 s_one 和 s_two 狀態(tài)的變化只會影響其對應的視圖,而不會影響到無關的視圖了。于是乎我們利用自定義子視圖避免了無必要的“冗余”刷新操作。
這只是一個非常簡單的例子,在包含大量狀態(tài)的復雜界面中,利用自定義子視圖無疑會帶來可觀的界面渲染性能提升!棒棒噠!💯🚀
總結在本篇博文里,我們討論了 SwiftUI 中利用子視圖代替父視圖界面布局內容的重要優(yōu)勢,并為大家舉了一個非常通俗易懂的例子。
那么,感謝觀賞,再會!😎
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
本文名稱:SwiftUI中為什么應該經常用子視圖替換父視圖中的大段內容?-創(chuàng)新互聯
網站URL:http://muchs.cn/article30/cshiso.html
成都網站建設公司_創(chuàng)新互聯,為您提供網站營銷、虛擬主機、企業(yè)建站、App設計、網站建設、網站策劃
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯