什么是@ViewBuilder?
從字面意思去理解 ViewBuilder 就是視圖構(gòu)建
弄匕,其主要使用場(chǎng)景就是構(gòu)建視圖恨豁。
在Apple的官方文檔中有這樣一句話
allowing those closures to provide multiple child views
允許閉包中提供多個(gè)子視圖
就是對(duì)@ViewBuilder的最好的解釋。
不使用@ViewBuilder時(shí)你只能傳遞一個(gè)View在閉包里激挪,使用@ViewBuilder你可以傳遞多個(gè)View到閉包里面
結(jié)合ViewBuilder和便利構(gòu)造函數(shù)使代碼更優(yōu)美辰狡。
可以在項(xiàng)目中通過ViewBuilder注解和便利構(gòu)造函數(shù)把許多具體相同特點(diǎn)的View封裝起來,并且分離邏輯代碼和視圖垄分,提升代碼的可復(fù)用性宛篇,并增強(qiáng)可讀性。
看了下面的例子你可能就會(huì)對(duì)@ViewBuilder結(jié)合便利構(gòu)造器的使用有一個(gè)更好的理解薄湿。
如果我們想要設(shè)置一個(gè)Text的背景為紅色叫倍,圓角為5。我們可能這樣去寫
Text("Liaoworking")
.background(Color.red)
.cornerRadius(5)
后來產(chǎn)品加需求了: 圖片也是紅色的背景豺瘤,圓角為5:
Image("Liaoworking")
.background(Color.red)
.cornerRadius(5)
再后來產(chǎn)品又加需求:一些自定義視圖也是紅色的背景吆倦,圓角為5:
這里假設(shè)我們的自定義視圖類為MyView
MyView()
.background(Color.red)
.cornerRadius(5)
聰明的你肯定想到了用一個(gè)View的extension來統(tǒng)一處理。
extension View {
func addRedBGWithRoundCorner() -> some View {
self
.background(Color.red)
.cornerRadius(5)
}
}
//調(diào)用:
Text("Liaoworking").addRedBGWithRoundCorner()
這樣做的確可以達(dá)到相同的效果坐求,而且代碼也會(huì)簡(jiǎn)潔不少蚕泽。
這個(gè)時(shí)候你還可以用@ViewBuilder
注解來創(chuàng)建你的自定義視圖達(dá)到相同的效果:
struct RedBackgroundAndCornerView<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
content
.background(Color.red)
.cornerRadius(5)
}
}
使用方法如下:
RedBackgroundAndCornerView {
Text("liaoworking")
}
兩種封裝的最后效果都是一樣的,你可能會(huì)覺得桥嗤,View的extension封裝要比@ViewBuilder 封裝 好太多
须妻。代碼都少寫很多。
但是突然有一天泛领,你的產(chǎn)品經(jīng)理決定再加一個(gè)功能璧南,在Text("liaowokring") 右邊再加一個(gè)圖片。
如果使用如果不使用@ViewBuilder關(guān)鍵字的話 你必須要用一個(gè)HStack把兩個(gè)元素包裹住才能編譯通過师逸。
RedBackgroundAndCornerView {
HStack {
Text("liaoworking")
Image("hello")
}
}
但是當(dāng)你使用了@ViewBuilder 關(guān)鍵字 你可以不需要HStack包裹,直接寫豆混,和HStack包裹效果一樣:
RedBackgroundAndCornerView {
Text("liaoworking")
Image("hello")
}
除此之外 @ViewBuilder 還有一個(gè)更好用的地方
可能你在開發(fā)中經(jīng)常會(huì)遇到下面這個(gè)編譯報(bào)錯(cuò)
Function declares an opaque return type 'some View', but the return statements in its body do not have matching underlying types
就是當(dāng)你不同的條件下返回的視圖不同時(shí)編譯器不允許你有這樣的寫法篓像。
相信每一位SwiftUI的初學(xué)者都遇到過這樣的報(bào)錯(cuò)。
這個(gè)時(shí)候就可以用神器 @ViewBuilder 去標(biāo)注你的content屬性
皿伺, 可以順利的編譯并且按照你所設(shè)想的方式運(yùn)行员辩。
注:@ViewBuilder 不僅可以標(biāo)注計(jì)算型屬性,還可以標(biāo)注func
用法同理鸵鸥。
over.