SwiftUI 接收自定义事件
SwiftUI receive custom Event
我有一个 ObservableObject
使用 @Published
属性 包装器发布一些值。此对象还包含一个计时器。
问题是,如何在计时器执行后立即触发事件并在 SwiftUI 的视图中处理该事件(我更喜欢使用 onReceive
之类的东西)?
已经使用 Combine 框架来发布变化的值,我想正确地实现这个事件触发/处理。但到目前为止,我所读到的关于 Combine 的所有内容都是关于处理值变化的。但在我的例子中,它只是一个简单的事件(没有任何值)。
我知道我可以简单地使用闭包并在计时器到期时调用它,如果没有更好的类似组合的解决方案,我会这样做。
这是一个非常简单的问题的概念性问题,所以我认为无需我提供代码示例就可以自我解释?
只是一个想法,但您可以将特定线程专用于该对象吗?然后专门在该队列上监听和触发事物。我以前从未这样做过,但这似乎是正确的想法。
https://developer.apple.com/documentation/dispatch/dispatchqueue
SwiftUI 与 Combine 一起工作的方式是通过 .onReceive
,它需要一个发布者。对象可以公开发布者 - 无论是 Timer
还是其他 - 作为 属性.
Combine 发布者通过发出值来工作,如果您只需要发出事件发生的信号,您可以发出 ()
又名 Void
值。
顺便说一句,这个对象不一定是 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。例如,如果某个随机事件发生,您可以使用 PassthroughSubject
来发布一个值:
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()
}
}
}
我有一个 ObservableObject
使用 @Published
属性 包装器发布一些值。此对象还包含一个计时器。
问题是,如何在计时器执行后立即触发事件并在 SwiftUI 的视图中处理该事件(我更喜欢使用 onReceive
之类的东西)?
已经使用 Combine 框架来发布变化的值,我想正确地实现这个事件触发/处理。但到目前为止,我所读到的关于 Combine 的所有内容都是关于处理值变化的。但在我的例子中,它只是一个简单的事件(没有任何值)。
我知道我可以简单地使用闭包并在计时器到期时调用它,如果没有更好的类似组合的解决方案,我会这样做。
这是一个非常简单的问题的概念性问题,所以我认为无需我提供代码示例就可以自我解释?
只是一个想法,但您可以将特定线程专用于该对象吗?然后专门在该队列上监听和触发事物。我以前从未这样做过,但这似乎是正确的想法。
https://developer.apple.com/documentation/dispatch/dispatchqueue
SwiftUI 与 Combine 一起工作的方式是通过 .onReceive
,它需要一个发布者。对象可以公开发布者 - 无论是 Timer
还是其他 - 作为 属性.
Combine 发布者通过发出值来工作,如果您只需要发出事件发生的信号,您可以发出 ()
又名 Void
值。
顺便说一句,这个对象不一定是 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。例如,如果某个随机事件发生,您可以使用 PassthroughSubject
来发布一个值:
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()
}
}
}