![](/img/trans.png)
[英]How to make a view that takes a Binding and passes it to another Binding in the view - SwiftUI
[英]How can I make my View stop unnecessary rendering with using CustomType for Binding in SwiftUI?
我有一個名為AppData的CustomType ,它看起來像這樣:
struct AppData {
var stringOfText: String
var colorOfText: Color
}
我在我的視圖中使用這個AppData作為 State 或 Binding,我的項目中有2 個視圖稱為: ContentView和另一個稱為BindingView 。 在我的BindingView中,我只是使用AppData的顏色信息。 我期待我的BindingView呈現或響應顏色信息的變化! 實際上BindingView甚至會為stringOfText
呈現自己,這是完全沒有必要的,因為 View 中沒有使用該數據。 我認為也許BindingView不僅考慮colorOfText
,而且還考慮所有攜帶這些數據的 package ,即 appData 所以我決定幫助BindingView了解它應該何時呈現自己,並且我制作了 View Equatable ,但這甚至沒有幫助。 仍然BindingView在浪費渲染的stringOfText
更改時刷新和渲染自身。 在將CustomType用作 State 或 Binding 的類型時,如何解決這個不必要的渲染問題。
struct ContentView: View {
@State private var appData: AppData = AppData(stringOfText: "Hello, world!", colorOfText: Color.purple)
var body: some View {
print("rendering ContentView")
return VStack(spacing: 20) {
Spacer()
EquatableView(content: BindingView(appData: $appData))
//BindingView(appData: $appData).equatable()
Spacer()
Button("update stringOfText from ContentView") { appData.stringOfText += " updated"}
Button("update colorOfText from ContentView") { appData.colorOfText = Color.red }
Spacer()
}
}
}
struct BindingView: View, Equatable {
@Binding var appData: AppData
var body: some View {
print("rendering BindingView")
return Text("123")
.bold()
.foregroundColor(appData.colorOfText)
}
static func == (lhs: BindingView, rhs: BindingView) -> Bool {
print("Equatable function used!")
return lhs.appData.colorOfText == rhs.appData.colorOfText
}
}
在Views
上使用Equatable
(和.equatable()
、 EquatableView()
)時,SwiftUI 會做出一些決定,決定何時應用我們自己的==
函數以及何時自行比較參數。 在此處查看我的另一個答案以及更多詳細信息: https://stackoverflow.com/a/66617961/560942
在這種情況下,似乎即使聲明了Equatable
, SwiftUI 也會跳過它,因為它必須確定Binding
中的POD
(普通舊數據)被確定為不相等,因此它將刷新視圖(再次,即使有人會認為==
足以迫使它不要這樣做)。
在您給出的示例中,系統重新渲染Text
元素顯然是微不足道的,因此重新渲染是否發生並不重要。 但是,即使重新渲染確實會產生后果,您也可以將不變的部分封裝到單獨的子視圖中:
struct BindingView: View {
@Binding var appData: AppData
var body: some View {
print("rendering BindingView")
return BindingChildView(color: appData.colorOfText)
}
//no point in declaring == since it won't get called (at least with the current parameters
}
struct BindingChildView : View {
var color: Color
var body: some View {
print("rendering BindingChildView")
return Text("123")
.bold()
.foregroundColor(color)
}
}
在上面的代碼中,雖然每次都重新渲染BindingView
(雖然成本基本為零,因為什么都不會改變),但是新的子視圖被跳過了,因為它的參數是 equatable 的(即使沒有聲明 Equatable)。 因此,在一個非人為的示例中,如果子視圖的渲染成本很高,這將解決問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.