SwiftUI 接收自定义事件

SwiftUI receive custom Event

我有一个 ObservableObject 使用 @Published 属性 包装器发布一些值。此对象还包含一个计时器。

问题是,如何在计时器执行后立即触发事件并在 SwiftUI 的视图中处理该事件(我更喜欢使用 onReceive 之类的东西)? 已经使用 Combine 框架来发布变化的值,我想正确地实现这个事件触发/处理。但到目前为止,我所读到的关于 Combine 的所有内容都是关于处理值变化的。但在我的例子中,它只是一个简单的事件(没有任何值)。

我知道我可以简单地使用闭包并在计时器到期时调用它,如果没有更好的类似组合的解决方案,我会这样做。

这是一个非常简单的问题的概念性问题,所以我认为无需我提供代码示例就可以自我解释?

只是一个想法,但您可以将特定线程专用于该对象吗?然后专门在该队列上监听和触发事物。我以前从未这样做过,但这似乎是正确的想法。

https://developer.apple.com/documentation/dispatch/dispatchqueue

https://www.freecodecamp.org/news/ios-concurrency/

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()
      }
   }
}