swift - SwiftUI 接收自定义事件
问题描述
我有一个ObservableObject
使用@Published
属性包装器发布一些值的方法。该对象还包含一个计时器。
问题是,如何在执行计时器后立即触发事件并在 SwiftUI 的视图中处理该事件(我更喜欢使用类似的东西onReceive
)?已经使用组合框架来发布变化的值,我想正确地实现这个事件触发/处理。但是到目前为止,我所读到的关于 Combine 的所有内容都是关于处理值变化的。但在我的情况下,它只是一个简单的事件(没有任何值)。
我知道我可以简单地使用闭包并在计时器到期时调用它,如果没有更好的类似组合的解决方案,我会这样做。
这是一个非常简单的问题的概念性问题,所以我认为它是自我解释的,而无需我提出代码示例?
解决方案
SwiftUI 与 Combine 一起使用的方式是 via .onReceive
,它需要一个发布者。一个对象可以公开一个发布者——无论Timer
是其他什么——作为一个属性。
通过发出值来组合发布者的工作,如果您只需要发出事件发生的信号,您可以发出()
akaVoid
值。
顺便说一下,这个对象不必是ObservableObject
,但它可以是。
class Foo: ObservableObject {
let timer = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.map { _ in } // map to Void
.eraseToAnyPublisher() // optional, but a good practice
}
现在,您可以使用.onReceive
来订阅timer
事件:
struct ContentView: View {
@StateObject var foo = Foo()
@State var int: Int = 0
var body: some View {
Text("\(int)")
.onReceive(timer) {
self.int += 1
}
}
}
当然,您不仅限于 TimerPublisher。例如,如果发生了一些随机事件,您可以使用 aPassthroughSubject
来发布一个值:
class Foo {
let eventA: AnyPublisher<Void, Never>
private let subject = PassthroughSubject<Void, Never>()
init() {
eventA = subject.eraseToAnyPublisher()
let delay = Double.random(in: 10...100)
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
// something random happened, notify
self?.subject.send()
}
}
}
推荐阅读
- javascript - javascript 表单发送问题
- system - WebAssembly (&WASI) 中的堆栈空间
- r - dplyr 用于大小写控制匹配
- apache-zookeeper - 更改 zookeeper 节点的顺序
- prometheus - 无需目标服务器配置即可将指标发送到集中式 Prometheus 服务器
- c# - 如何复制整个网格并将其复制到 WPF 中的其他列表框
- python - SQL 如何指示一个 ID 是否曾经返回一个值?
- python - 如何设置环境变量?
- python - 解析两个文件以汇集数据并创建新的 Fasta 文件
- c# - 从后面的代码设置时,MaterialDesignDataGridComboBoxColumn ItemSource 共享一个 CollectionViewSource 实例