EquatableView 不强制 SwiftUI 使用 == 函数的自定义实现

EquatableView not forcing SwiftUI to use custom implementation of the == function

我无法按照文章使用 EquatableView:Link1 and link2。我希望每次单击按钮时都会调用 TestView 中的“==”函数。

我是不是漏掉了什么?

struct ContentView: View {   
    @State var state = false   
    var body: some View {
        VStack {
            EquatableView(content: TestView(state: $state))
            Button("Change state", action: {state.toggle()})
        }
    }
}

struct TestView: View, Equatable {
    @Binding var state: Bool
    var body: some View {
        let _ = print("Test updated")
        Text("TestView state : \(state.description)")
    }
    static func == (lhs: TestView, rhs: TestView) -> Bool {
        //Never printed or invoked
        let _ = print ("lhs == rhs invoked  \(lhs.state) == \(rhs.state)") 
        return lhs.state == rhs.state
    }
}

更新:

在 Alperen 的非常有帮助的回复之后,它表明必须添加“@State”才能触发 ==。但是,如下所示,将“@State”变量从父级直接传递到子视图的“@State”以获得相同的变量,这是没有意义的。

因此,我向 TestView 添加了另一个变量“@State var notUsed”,它将不起作用 除非“@Binding”被删除。人们还想比较“@Binding”变量,所以对我来说这是不合逻辑的。

我的问题仍然存在,我是不是遗漏了什么或者这种行为是设计使然的?

该代码有效。你能试试这个吗?

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}



struct ContentView: View {
    @State var state = false
    var body: some View {
        VStack {
            TestView(state: state).equatable()
            Button("Not Change", action: {})
            Button("Change", action: {state.toggle()})
           
        }
    }
}


struct TestView: View, Equatable {
    @State var state: Bool
    var body: some View {
        let _ = print("Test updated")
        Text("TestView state : \(state.description)")
    }
    static func == (lhs: TestView, rhs: TestView) -> Bool {
        //Never printed or invoked
        let _ = print ("lhs == rhs invoked  \(lhs.state) == \(rhs.state)")
        return lhs.state == rhs.state
    }
}

Equatable 在创建视图时使用,因此它要么替换已经存在的,要么不替换。在你的例子中 TestView 没有被重新创建,因为它不应该在绑定上改变 - 只有 body 用新值呈现。

模拟游戏(测试用)最简单的就是添加条件。 Equatibility 只是一种优化技术,它可以帮助 SwiftUI 检测是否替换现有视图实例。

这里是演示 Equatable 作品的更新示例。使用 Xcode 12.1 / iOS 14.1

测试
struct ContentView: View {
    @State var state = false
    var body: some View {
        VStack {
            if state {
               EquatableView(content: TestView(state: $state))
            }
            Button("Change state", action: {state.toggle()})
        }
    }
}

struct TestView: View, Equatable {
    @Binding var state: Bool
    init(state: Binding<Bool>) {
        _state = state
        print(">> inited")        // << check if created
    }
    var body: some View {
        let _ = print("Test updated")
        Text("TestView state : \(state.description)")
    }
    static func == (lhs: TestView, rhs: TestView) -> Bool {
        //Never printed or invoked
        let _ = print ("lhs == rhs invoked  \(lhs.state) == \(rhs.state)")
        return lhs.state == rhs.state
    }
}