本文介绍了在 SwiftUI 视图中组合 onChange 和 onAppear 事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 onChange 修饰符观察视图上的属性.但是,我也希望在初始值上运行同一段代码,因为有时数据会被注入初始化程序或稍后异步加载.

I'm observe a property on a view using the onChange modifier. However, I'd also like the same piece of code to run on the initial value as well because sometimes the data is injected in the initializer or asynchronously loaded later.

例如,我有一个注入模型的视图.有时,此模型开始时包含数据(如预览),或者从网络异步检索.

For example, I have a view that gets a model injected. Sometimes this model has data in it to begin with (like previews), or is asynchronously retrieved from the network.

class MyModel: ObservableObject {
    @Published var counter = 0
}

struct ContentView: View {
    @ObservedObject var model: MyModel

    var body: some View {
        VStack {
            Text("Counter: (model.counter)")
            Button("Increment") { model.counter += 1 }
        }
        .onChange(of: model.counter, perform: someLogic)
        .onAppear { someLogic(counter: model.counter) }
    }

    private func someLogic(counter: Int) {
        print("onAppear: (counter)")
    }
}

onAppearonChange 两种情况下,我想运行 someLogic(counter:).有没有更好的方法来获得这种行为或将它们结合起来?

In both onAppear and onChange cases, I'd like to run someLogic(counter:). Is there a better way to get this behaviour or combine them?

推荐答案

看起来 onReceive 可能正是您所需要的.而不是:

It looks like onReceive may be what you need. Instead of:

.onChange(of: model.counter, perform: someLogic)
.onAppear { someLogic(counter: model.counter) }

你可以这样做:

.onReceive(model.$counter, perform: someLogic)

onChangeonReceive 之间的区别在于后者也会在视图初始化时触发.

The difference between onChange and onReceive is that the latter also fires when the view is initialised.

onChange

如果您仔细查看 onChange,您会发现它仅在值 更改 时才执行操作(而当视图发生变化时不会发生这种情况)已初始化).

If you take a closer look at onChange, you'll see that it performs an action only when a value changes (and this doesn't happen when a view is initialised).

/// Adds a modifier for this view that fires an action when a specific
/// value changes.
/// ...
@inlinable public func onChange<V>(of value: V, perform action: @escaping (V) -> Void) -> some View where V : Equatable


onReceive

然而,计数器的发布者也会在初始化视图时发出该值.这将使 onReceive 执行作为参数传递的操作.

However, the counter's publisher will emit the value also when a view is initialised. This will make onReceive perform an action passed as a parameter.

/// Adds an action to perform when this view detects data emitted by the
/// given publisher.
/// ...
@inlinable public func onReceive<P>(_ publisher: P, perform action: @escaping (P.Output) -> Void) -> some View where P : Publisher, P.Failure == Never


请注意onReceive不是等价onChange+onAppear.

onAppear 在视图出现时被调用,但在某些情况下,视图可能会在不触发 onAppear 的情况下再次初始化.

onAppear is called when a view appears but in some cases a view may be initialised again without firing onAppear.

这篇关于在 SwiftUI 视图中组合 onChange 和 onAppear 事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 06:31