【问题标题】:EquatableView not forcing SwiftUI to use custom implementation of the == functionEquatableView 不强制 SwiftUI 使用 == 函数的自定义实现
【发布时间】:2021-03-28 15:44:16
【问题描述】:

我无法根据文章使用 EquatableView:Link1link2。我希望每次单击按钮时都会调用 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” var 直接传递给同一 var 的 SubView 的“@State”是没有意义的。

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

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

【问题讨论】:

    标签: swift xcode view swiftui state


    【解决方案1】:

    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
        }
    }
    

    【讨论】:

    • 谢谢!只是为了澄清一下,您为什么说“出于测试目的”。我想用它来优化导致问题的视图之一。为什么不在生产代码中初始化“_state = state”?
    【解决方案2】:

    该代码正在运行。你可以试试这个吗?

    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
        }
    }
    

    【讨论】:

    • 我以前见过,如果你运行它,你会发现它不起作用。同样的行为,== 没有被调用。
    • @Alperen,你正在做一些事情......我会更新我的帖子,因为回复很长。仅供参考:the link you sent 最初也没有工作,因为它没有“@State”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多