问题描述
我正在使用 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)")
}
}
在 onAppear
和 onChange
两种情况下,我想运行 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)
onChange
和 onReceive
之间的区别在于后者也会在视图初始化时触发.
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 事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!