It looks like onReceive
may be what you need. Instead of:
.onChange(of: model.counter, perform: someLogic)
.onAppear { someLogic(counter: model.counter) }
you could do:
.onReceive(model.$counter, perform: someLogic)
The difference between onChange
and onReceive
is that the latter also fires when the view is initialised.
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
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
Just note that onReceive
is not an equivalent of onChange
+onAppear
.
onAppear
is called when a view appears but in some cases a view may be initialised again without firing onAppear
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…