我正在尝试使用 EquatableView 作为我的视图,但 SwiftUI 不使用我的 == 函数,看来我做的一切都是正确的,但不起作用,需要帮助。我想使用 == 函数来阻止 SwiftUI 进行不必要的渲染,但它每次都会渲染并且不使用给定的函数,为什么?
import SwiftUI
extension Int { var isEven: Bool { return self % 2 == 0 } }
Run Code Online (Sandbox Code Playgroud)
struct ContentView: View {
@State private var number = 3
var body: some View {
VStack {
// EquatableView ( content: NumberView(number: number) ) // <<: Here
// NumberView(number: number).equatable() // <<: Or Here
Button("New Random Number") {
number = Int.random(in: 1...100)
}
Text(number.description).bold().padding()
}
}
}
Run Code Online (Sandbox Code Playgroud)
struct NumberView: View, Equatable {
let number: Int
init(number: Int) {
print("initializing")
self.number = number
}
var body: some View {
print("rendering")
return VStack {
if number.isEven {
Text("EVEN").bold().foregroundColor(Color.green)
} else {
Text("ODD").bold().foregroundColor(Color.red)
}
}
.padding()
}
static func == (lhs: NumberView, rhs: NumberView) -> Bool {
print("Equatable used!")
return lhs.number.isEven == rhs.number.isEven
}
}
Run Code Online (Sandbox Code Playgroud)
(Xcode 12.4、macOS 11.2.3)
\n其机制equatable()
有点不透明。事实上,所有标题都有这个(当然不详细)定义:
\n\n当新值与其旧值相同时,防止视图更新其子视图。
\n
例如,人们会假设在您最初的示例中,您==
将被调用来评估视图是否相等。但是,显然这不会发生。
它可以通过多种(有时是令人惊讶的)方式被迫发生。例如(这个是不足为奇的),如果您在NumberView
该@State
属性上添加一个附加属性,则==
每次都会调用您的属性:
\nstruct NumberView: View, Equatable {\n \n var number: Int = 0\n @State var additionalProp: Int = 0\n \n var body: some View {\n print("rendering \\(Date()): \\(number)")\n return VStack {\n Text("\\(number)")\n if number.isEven {\n Text("EVEN").bold().foregroundColor(Color.green)\n } else {\n Text("ODD").bold().foregroundColor(Color.red)\n }\n }\n .padding()\n }\n\n static func == (lhs: NumberView, rhs: NumberView) -> Bool {\n print("Equatable used!")\n return lhs.number.isEven == rhs.number.isEven\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n其行为与以下内容不同(其中==
未调用):
var number: Int = 0\nvar additionalProp: Int = 0\n
Run Code Online (Sandbox Code Playgroud)\n由此,我想我们可以推断出以下几点:
\nView
没有其他属性,SwiftUI 将对 props 进行相等性检查,如果它们不相等,它甚至不会调用你的equatable
函数这是对我来说更有趣的案例:
\nstruct NumberView: View, Equatable {\n \n var number: Int = 0\n var additionalProp: String = ""\n \n var body: some View {\n print("rendering \\(Date()): \\(number)")\n return VStack {\n Text("\\(number)")\n if number.isEven {\n Text("EVEN").bold().foregroundColor(Color.green)\n } else {\n Text("ODD").bold().foregroundColor(Color.red)\n }\n }\n .padding()\n }\n\n static func == (lhs: NumberView, rhs: NumberView) -> Bool {\n print("Equatable used!")\n return lhs.number.isEven == rhs.number.isEven\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n在上面的情况下,equatable 函数将再次被使用,即使它String
是 Swift 中的值类型(和 Equatable)并且不使用@State
. 我对那部分没有很好的解释。
\n\nSwiftUI 假设任何 Equatable.== 都是真正的相等检查,因此对于 POD 视图,它直接比较每个字段(通过反射)。对于非 POD 视图,它更喜欢 view\xe2\x80\x99s ==,但如果没有 ==,则回退到其自己的字段比较。EqView 是一种强制使用 == 的方法。\n当它进行每个字段比较时,相同的规则将递归地应用于每个字段(选择直接比较或 == 如果已定义)。(POD = 纯数据,请参阅 Swift\xe2\x80\x99s _isPOD() 函数。)
\n
归档时间: |
|
查看次数: |
2100 次 |
最近记录: |