SwiftUI 精簡程式的 5 個方法
Published in
6 min readFeb 11, 2021
開發 SwiftUI App 時,我們時常串接大量的 modifier,因此造成程式有點雜亂,比方以下 background ( ) 裡設定背景漸層的程式碼。
struct ContentView: View {
var body: some View {
Image("天竺鼠車車")
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipShape(.circle)
.background(
LinearGradient(gradient: Gradient(colors: [.red, .blue]), startPoint: .leading, endPoint: .trailing)
.frame(width: 250, height: 250)
.rotationEffect(.degrees(10))
)
.shadow(color: .black, radius: 10)
}
}
此時我們可利用以下 5 種方法精簡程式:
- 利用 Extract Subview 將 view 獨立出來
- 定義回傳 view 的 computed property
- 定義回傳 view 的 method
- body 裡宣告儲存 view 的常數
- 自訂組合 modifier 的 function 或透過 ViewModifier 實作 custom modifier
利用 Extract Subview 將 view 獨立出來
在 LinearGradient 上按出右鍵選單,然後點選 Extract Subview。
struct ContentView: View {
var body: some View {
Image("天竺鼠車車")
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipShape(.circle)
.background(BackgroundView())
.shadow(color: .black, radius: 10)
}
}
struct BackgroundView: View {
var body: some View {
LinearGradient(gradient: Gradient(colors: [.red, .blue]), startPoint: .leading, endPoint: .trailing)
.frame(width: 250, height: 250)
.rotationEffect(.degrees(10))
}
}
定義回傳 view 的 computed property
struct ContentView: View {
var backgroundView: some View {
LinearGradient(gradient: Gradient(colors: [.red, .blue]), startPoint: .leading, endPoint: .trailing)
.frame(width: 250, height: 250)
.rotationEffect(.degrees(10))
}
var body: some View {
Image("天竺鼠車車")
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipShape(.circle)
.background(backgroundView)
.shadow(color: .black, radius: 10)
}
}
值得注意的,以上程式的 computed property 型別必須宣告為 some View,而不是 LinearGradient,因為加了 modifier 後它的型別將不再是 LinearGradient。
定義回傳 view 的 method
定義回傳 view 的 method 概念和剛剛的 computed property 類似,不過由於它是 function,所以多了一些彈性,我們可以傳入參數,比方調整旋轉的角度。
struct ContentView: View {
func backgroundView(degrees: Double) -> some View {
LinearGradient(gradient: Gradient(colors: [.red, .blue]), startPoint: .leading, endPoint: .trailing)
.frame(width: 250, height: 250)
.rotationEffect(.degrees(degrees))
}
var body: some View {
Image("天竺鼠車車")
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipShape(.circle)
.background(backgroundView(degrees: 60))
.shadow(color: .black, radius: 10)
}
}
body 裡宣告儲存 view 的常數
struct ContentView: View {
var body: some View {
let backgroundView = LinearGradient(gradient: Gradient(colors: [.red, .blue]), startPoint: .leading, endPoint: .trailing)
.frame(width: 250, height: 250)
.rotationEffect(.degrees(10))
return Image("天竺鼠車車")
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipShape(.circle)
.background(backgroundView)
.shadow(color: .black, radius: 10)
}
}