![](/img/trans.png)
[英]Can I use a button inside a SwiftUI sheet view that appears on top of my main SwiftUI view to change a subview inside the main view?
[英]Why I can not use Equatable function in my View when the View can use it in SwiftUI?
我正在尝试将 EquatableView 用于我的视图,但 SwiftUI 不使用我的 == function,看来我做的一切都正确,但不起作用,需要帮助。 我想停止 SwiftUI 进行不必要的渲染,也使用我的 == function,但它每次都渲染并且不使用给定的 function,为什么?
import SwiftUI
extension Int { var isEven: Bool { return self % 2 == 0 } }
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()
}
}
}
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
}
}
(Xcode 12.4、macOS 11.2.3)
equatable()
的机制有点不透明。 事实上,所有标题都有这个(当然不是详细的)定义:
当新值与旧值相同时,防止视图更新其子视图。
例如,人们会假设对于您的原始示例,您的==
将被调用以评估视图是否相等。 但是,显然这不会发生。
它可以以多种(有时令人惊讶的)方式被迫发生。 例如(这个并不令人惊讶),如果您在NumberView
上添加一个附加属性,即@State
属性,则您的==
每次都会被调用:
struct NumberView: View, Equatable {
var number: Int = 0
@State var additionalProp: Int = 0
var body: some View {
print("rendering \(Date()): \(number)")
return VStack {
Text("\(number)")
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
}
}
它的行为与以下不同(其中==
未被调用):
var number: Int = 0
var additionalProp: Int = 0
由此,我认为我们可以推断出以下几点:
equatable
这是对我来说更有趣的案例:
struct NumberView: View, Equatable {
var number: Int = 0
var additionalProp: String = ""
var body: some View {
print("rendering \(Date()): \(number)")
return VStack {
Text("\(number)")
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
}
}
在上述情况下,即使String
是 Swift 中的值类型(和 Equatable)并且不使用 @State ,也会再次使用可相等的@State
。 我对那部分没有很好的解释。
SwiftUI 假定任何 Equatable.== 是真正的相等检查,因此对于 POD 视图,它直接比较每个字段(通过反射)。 对于非 POD 视图,它更喜欢视图的 ==,但如果没有 ==,则回退到其自己的字段比较。 EqView 是一种强制使用 == 的方法。 当它对每个字段进行比较时,相同的规则会递归地应用于每个字段(选择直接比较或 == 如果已定义)。 (POD = 纯数据,参见 Swift 的 _isPOD() function。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.