【问题标题】:Mirror Binding value with Published in SwiftUI在 SwiftUI 中使用 Published 镜像绑定值
【发布时间】:2022-09-27 19:03:58
【问题描述】:

如何将 View 的 Binding 值连接到 ObservableObject 的 Published 值?

目标:objValue 的所有变化都会反映在 viewValue 上,反之亦然。

注意:不要建议直接 onChange(obj.objValue) { viewValue = $0 } 修饰符。它会触发额外的 View 绘制周期(第一个是 objValue,第二个是 viewValue)。

class MyObject: ObservableObject {
    @Published var objValue: Int = 0
}

struct MyView: View {
    @Binding var viewValue: Int
    @StateObject var obj = MyObject()
    
    var body: some View {
        Text(\"Placeholder\")
            .onChange(viewValue) {
                //Do something
            }
    }
}
  • 为什么不通过MyObject 而不是Int
  • 因为这里被用作StateObject,所以不需要增加复杂性和冲动客户端来创建和注入100%用于View内部目的的MyObject。
  • 示例:假设您必须将不同的对象注入到任何标准组件中,例如 Text 或 VStack。
  • 您是否有理由不只是在 onChange 中使用obj.objValue
  • 将修饰符 .onChange 添加到 Text(\"Placeholder\") 完全没用,文本永远不会改变。

标签: swift swiftui combine


【解决方案1】:

这是使用 View 适配器的工作解决方案(尚未直接使用 Combine),它让我们避免额外重绘 MyView 主体。 通过将 Binding 值传递给 ValueReader View,只有它的主体会被触发重绘,然后它只是将新结果传递到外面,我们可以使用它。这里我们将 viewValue 的更新值赋值给 objValue。

这种技术避免了额外的重绘周期,MyView body 将只重绘一次,无论是先更改 objValue 还是 viewValue。 因为 viewValue 没有直接在 body 中使用,只有 ValueReader 会在 viewValue 更改时直接重绘,跳过 MyView 的 body 重绘。

class MyObject: ObservableObject {
    @Published var objValue: Int = 0
}

struct MyView: View {
    @Binding var viewValue: Int
    @StateObject var obj = MyObject()
    
    var body: some View {
        ZStack {
            ValueReader(value: $viewValue) { newValue in
                obj.objValue = newValue //Mirroring viewValue to obj.objValue
            }
            
            Text("Placeholder")
                .onChange(of: obj.objValue, perform: handleValue)
        }
    }
    
    private func handleValue(_ value: Int) {
        viewValue = value //Mirroring obj.objValue to viewValue

        //Do any job here. For example just send analytics
    }
    
    private struct ValueReader: View {
        @Binding var value: Int
        let onChange: (_ newValue: Int) -> ()
        
        var body: some View {
            Color.clear
                .onChange(of: value) { newValue in
                    onChange(newValue)
                }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多