我有一个模拟模型,它应该在后台每0.5-5秒(大约(更新一次,频率是模型状态的函数。
我使用的是一个SwiftUI应用程序,它显示了这个模拟模型中的一些数据,SwiftUI界面已经很好地从模型中提取了发布的数据。我目前有一些外部控件(例如滑块、切换按钮等(,可以用来操纵模型的状态,这反映在显示数据的SwiftUI视图中。我现在想做的是让模型在计时器上自我更新(同样,它是一个模拟器(,当发布的数据发生变化时,SwiftUI已经处理了用更新的数据重新绘制视图的问题。
所以我想做的是:
class MyModel: ObservableObject {
static let shared shared = MyModel()
@Published var coolData1: CoolData()
@Published var coolData2: CoolData()
@Published var coolData3: CoolData()
var modelTimer = AnyPublisher<Date,Never>
func runModel() {
modelTimer = Timer.publish(every: 1, on: .main, in: .common)
.autoconnect()
.eraseToAnyPublisher()
// HERE I want updateModel() called every time the modelTimer fires and it should run in the background.
}
func pauseModel() {
modelTimer.upstream.connect().cancel()
}
func updateModel() {
update(coolData1)
update(coolData2)
update(coolData3)
}
}
我只是不知道在哪里,也不知道Combine/Timer的具体语法,以使模型在我的动态计划中更新,从而在后台运行。
谢谢你的帮助。
您已经创建了计时器发布程序,但没有人订阅。
要订阅它,您可以使用sink
发布者运算符。我直接在响应中输入这段代码,所以你可能需要调整它。首先,在你的类中添加一个字段来保存订阅:
class MyModel: ObservableObject {
static let shared shared = MyModel()
var timerSubscription: AnyCancellable?
然后,在设置好计时器后,使用sink
订阅
// HERE I want updateModel() called every time the modelTimer fires and it should run in the background.
timerSubscription = modelTimer.sink { [weak self] _ in
guard nil != self { return }
self!.updateModel()
}
现在我注意到,您的计时器设置为在主运行循环中启动,因此目前订阅不会在后台运行。
您必须捕获订阅。如果您不这样做,则对sink
的调用将订阅,然后立即取消订阅。如果您想在任何时候取消订阅,可以使用timerSubscription.cancel
。