如何在 Combine 中使用另一个发布者重新发布 PassthroughSubject
How to re-publish a PassthroughSubject using another publisher in Combine
当前(工作)情况:
在我们的应用程序中,我们有多个 PassthroughSubject<Void, Never>
类型的发布者。
此发布者的订阅者在 .sink()
闭包内发送相同类型的发布者。在一个简单的操场上,它看起来像这样:
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
import Combine
class MyViewController : UIViewController {
// MARK: - Observables
let initialPublisher: PassthroughSubject = PassthroughSubject<Void, Never>()
let rePublisher = PassthroughSubject<Void, Never>()
// MARK: - Observer
private var cancellableSubscriber = Set<AnyCancellable>()
override func loadView() {
// MARK: - View Setup
let view = UIView()
let button = UIButton(type: .system)
button.frame = CGRect(x: 100, y: 100, width: 200, height: 20)
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
view.addSubview(button)
self.view = view
// MARK: - Subscriptions
// Event of initial publisher is received and re-published using another subject.
initialPublisher
.sink { [weak self] in
self?.rePublisher.send()
}
.store(in: &cancellableSubscriber)
// The re-published event is received.
rePublisher
.sink {
print("Received!")
}
.store(in: &cancellableSubscriber)
}
@objc private func buttonAction() {
self.initialPublisher.send()
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
首选(无效)解决方案:
我没有使用 .sink()
闭包和另一个 PassthroughSubject
订阅和重新发布,而是想使用 .receive(subscriber: AnySubscriber)
重新发布初始发布者但是不知何故它似乎不起作用或者我理解错了 .receive
方法。我尝试了以下但没有运气。
问题:
我怎样才能使下面的代码工作,或者它是否是正确的方法?如果没有,是否有比我们上面的代码更优雅的重新发布方式?
澄清:
如果有什么不清楚或者您需要更多示例,请在下面发表评论,我会尝试更新我的问题。
class MyViewController : UIViewController {
// MARK: - Observables
let initialPublisher: PassthroughSubject = PassthroughSubject<Void, Never>()
let rePublisher = PassthroughSubject<Void, Never>()
var subscriber = AnySubscriber<Void, Never>()
// MARK: - Observer
private var cancellableSubscriber = Set<AnyCancellable>()
override func loadView() {
// MARK: - View Setup
let view = UIView()
let button = UIButton(type: .system)
button.frame = CGRect(x: 100, y: 100, width: 200, height: 20)
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
view.addSubview(button)
self.view = view
// MARK: - Subscriptions
//Republishing
subscriber = AnySubscriber(initialPublisher)
// Event of initial publisher is received and re-published.
rePublisher.receive(subscriber: subscriber)
// // The re-published event is received.
rePublisher
.sink {
print("Received!") // <-- does not work!
}
.store(in: &cancellableSubscriber)
}
@objc private func buttonAction() {
self.initialPublisher.send()
}
}
我觉得你太辛苦了。只需传递 AnyPublisher 而不是试图将两个主题联系在一起。尝试将它们捆绑在一起甚至没有意义,因为任何人都可以在其中任何一个上调用发送。
class MyViewController : UIViewController {
let initialPublisher: PassthroughSubject = PassthroughSubject<Void, Never>()
var rePublisher: AnyPublisher<Void, Never> {
initialPublisher.eraseToAnyPublisher()
}
private var cancellableSubscriber = Set<AnyCancellable>()
override func loadView() {
super.loadView()
let button: UIButton = {
let result = UIButton(type: .system)
result.frame = CGRect(x: 100, y: 100, width: 200, height: 20)
result.setTitle("Button", for: .normal)
result.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
return result
}()
view.backgroundColor = .white
view.addSubview(button)
rePublisher
.sink {
print("Received!") // works!
}
.store(in: &cancellableSubscriber)
}
@objc private func buttonAction() {
initialPublisher.send()
}
}
当前(工作)情况:
在我们的应用程序中,我们有多个 PassthroughSubject<Void, Never>
类型的发布者。
此发布者的订阅者在 .sink()
闭包内发送相同类型的发布者。在一个简单的操场上,它看起来像这样:
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
import Combine
class MyViewController : UIViewController {
// MARK: - Observables
let initialPublisher: PassthroughSubject = PassthroughSubject<Void, Never>()
let rePublisher = PassthroughSubject<Void, Never>()
// MARK: - Observer
private var cancellableSubscriber = Set<AnyCancellable>()
override func loadView() {
// MARK: - View Setup
let view = UIView()
let button = UIButton(type: .system)
button.frame = CGRect(x: 100, y: 100, width: 200, height: 20)
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
view.addSubview(button)
self.view = view
// MARK: - Subscriptions
// Event of initial publisher is received and re-published using another subject.
initialPublisher
.sink { [weak self] in
self?.rePublisher.send()
}
.store(in: &cancellableSubscriber)
// The re-published event is received.
rePublisher
.sink {
print("Received!")
}
.store(in: &cancellableSubscriber)
}
@objc private func buttonAction() {
self.initialPublisher.send()
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
首选(无效)解决方案:
我没有使用 .sink()
闭包和另一个 PassthroughSubject
订阅和重新发布,而是想使用 .receive(subscriber: AnySubscriber)
重新发布初始发布者但是不知何故它似乎不起作用或者我理解错了 .receive
方法。我尝试了以下但没有运气。
问题:
我怎样才能使下面的代码工作,或者它是否是正确的方法?如果没有,是否有比我们上面的代码更优雅的重新发布方式?
澄清:
如果有什么不清楚或者您需要更多示例,请在下面发表评论,我会尝试更新我的问题。
class MyViewController : UIViewController {
// MARK: - Observables
let initialPublisher: PassthroughSubject = PassthroughSubject<Void, Never>()
let rePublisher = PassthroughSubject<Void, Never>()
var subscriber = AnySubscriber<Void, Never>()
// MARK: - Observer
private var cancellableSubscriber = Set<AnyCancellable>()
override func loadView() {
// MARK: - View Setup
let view = UIView()
let button = UIButton(type: .system)
button.frame = CGRect(x: 100, y: 100, width: 200, height: 20)
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
view.addSubview(button)
self.view = view
// MARK: - Subscriptions
//Republishing
subscriber = AnySubscriber(initialPublisher)
// Event of initial publisher is received and re-published.
rePublisher.receive(subscriber: subscriber)
// // The re-published event is received.
rePublisher
.sink {
print("Received!") // <-- does not work!
}
.store(in: &cancellableSubscriber)
}
@objc private func buttonAction() {
self.initialPublisher.send()
}
}
我觉得你太辛苦了。只需传递 AnyPublisher 而不是试图将两个主题联系在一起。尝试将它们捆绑在一起甚至没有意义,因为任何人都可以在其中任何一个上调用发送。
class MyViewController : UIViewController {
let initialPublisher: PassthroughSubject = PassthroughSubject<Void, Never>()
var rePublisher: AnyPublisher<Void, Never> {
initialPublisher.eraseToAnyPublisher()
}
private var cancellableSubscriber = Set<AnyCancellable>()
override func loadView() {
super.loadView()
let button: UIButton = {
let result = UIButton(type: .system)
result.frame = CGRect(x: 100, y: 100, width: 200, height: 20)
result.setTitle("Button", for: .normal)
result.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
return result
}()
view.backgroundColor = .white
view.addSubview(button)
rePublisher
.sink {
print("Received!") // works!
}
.store(in: &cancellableSubscriber)
}
@objc private func buttonAction() {
initialPublisher.send()
}
}