【问题标题】:SwiftUI/Combine: subscribe to value change of @BindingSwiftUI/Combine:订阅@Binding 的值变化
【发布时间】:2020-12-19 12:26:56
【问题描述】:

我有一个带有视图模型的视图,该视图中的操作可以更改视图模型。为了能够将逻辑分解为可重用的部分,我将视图的一部分作为它自己的视图,并带有一个 @Binding 到它需要具有的值。现在,我希望能够根据值更改执行一些逻辑,而不必只查看更改。我怎样才能做到这一点?如果它是一个常规属性,我会实现一个 didSet,但这让我无处可去。我想使用 Combine 并将 @Binding 视为发布者,但我也找不到这样做的方法。有什么建议吗?

代码如下:

class ViewModel: ObservableObject {
    @Published var counter: Int = 0
}

struct Greeter: View {
    @Binding var counter: Int {
        didSet {
            // this isn't printed....
            print("Did set -> \(counter)")
        }
    }
    
    init(counter: Binding<Int>) {
        self._counter = counter
        
        // ...so how about setting up a subscription to the @Binding counter above here?
    }
    
    var body: some View {
        Text("Hello, world #\(counter)!")
            .padding()
    }
}

struct ContentView: View {
    
    @ObservedObject var viewModel: ViewModel
    
    var body: some View {
        VStack {
            Greeter(counter: $viewModel.counter)
            Button("Go!") {
                viewModel.counter += 1
            }
        }
    }
}

所以我想保留数据在 ViewModel 中的结构,并且只有部分数据被传递到子视图。它在子视图(Greeter)中,我希望能够做一些事情(比如说打印 didSet 中的值)

【问题讨论】:

    标签: swift xcode swiftui combine


    【解决方案1】:

    这是可能的方法。使用 Xcode 11.4 / iOS 13.4 (SwiftUI 1.0+) 测试

    struct Greeter: View {
        @Binding var counter: Int
    
        var body: some View {
            Text("Hello, world #\(counter)!")
                .padding()
                .onReceive(Just(counter)) {    // << subscribe
                    print(">> greeter: \($0)") // << use !!
                }
        }
    }
    

    SwiftUI 2.0+ 的注意事项:您可以改用 .onChange(of: counter) {(实际上是上面的内置替换)

    【讨论】:

    • 感谢您的建议。 onChange 具有仅在值更改时才做出反应的额外好处,而 onReceive 也会在视图加载时触发
    • 花了我很长时间才找到它来支持 ios13,一个完美的 onChange 替代品,谢谢 :)
    • 每次刷新视图时都会调用它,不是吗?
    • 是的,是循环中的堆栈
    • 对我来说 .onReceive(Just(binding)) 有效,但 .onChange(of: binding) 无效。
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 2021-12-16
    • 1970-01-01
    • 2020-03-30
    • 2021-10-15
    • 2020-02-24
    • 1970-01-01
    • 2019-11-03
    相关资源
    最近更新 更多