我已经看到了如何使用来自某些NotificationCenter代码的发布者来进行转换,但是还没有看到如何实现这样的转换:
NotificationCenter.default.addObserver(
self,
selector: #selector(notCombine),
name: NSNotification.Name(rawValue: "notCombine"),
object: nil
)我已经看到这是作为发行者提供的,但是我selector没有,我不知道该为它做什么:
NotificationCenter.default.publisher(
for: Notification.Name(rawValue: "notCombine")
)有人知道吗?谢谢!
发布于 2019-10-27 22:46:02
你说的“我没有选择器”是对的,因为这是一半的道理。您可以在没有选择器的情况下从通知中心接收通知。
要点的另一半是,您可以将处理通知的逻辑向上推到组合管道中,这样,如果完全到达管道,正确的结果就会弹出管道的末尾。
老式的方式
假设我有一个Card视图,当通过发布通知来监听它时,它会发出虚拟尖叫:
static let tapped = Notification.Name("tapped")
@objc func tapped() {
NotificationCenter.default.post(name: Self.tapped, object: self)
}现在,为了示例的目的,假设游戏在收到这些通知之一时感兴趣的是发布通知的卡片的name属性的字符串值。如果我们用传统的方法去做,那么获取信息是一个两阶段的过程。首先,我们必须登记才能收到通知:
NotificationCenter.default.addObserver(self,
selector: #selector(cardTapped), name: Card.tapped, object: nil)然后,当我们收到通知时,我们必须查看它的object确实是一张卡片,如果是的话,获取它的name属性并使用它做一些事情:
@objc func cardTapped(_ n:Notification) {
if let card = n.object as? Card {
let name = card.name
print(name) // or something
}
}结合方式
现在,让我们使用组合框架来做同样的事情。我们通过调用通知中心的publisher方法从通知中心获得发布服务器。但我们不会就此止步。如果object不是卡,我们不希望收到通知,所以我们使用compactMap操作符将它安全地传递给Card (如果它不是Card,管道就会停止,就好像什么都没有发生一样)。我们只想要卡片的name,所以我们使用map操作符来获取它。结果如下:
let cardTappedCardNamePublisher =
NotificationCenter.default.publisher(for: Card.tapped)
.compactMap {$0.object as? Card}
.map {$0.name}假设cardTappedCardNamePublisher是视图控制器的实例属性。然后,我们现在拥有的是一个实例属性,如果卡片发布tapped通知,否则什么也不做,它就会发布一个字符串。
当我说逻辑被推上管道时,你明白我的意思吗?
那么,我们将如何安排接收从管道末端出来的东西呢?我们需要一个水槽:
let sink = self.cardTappedCardNamePublisher.sink {
print($0) // the string name of a card
}如果您尝试,您将看到,我们现在有一种情况,每次用户点击一张卡,卡的名字是打印出来的。这是我们先前的寄存器-一个观察者-和-一个选择器方法的组合。
发布于 2019-10-27 21:52:02
用例并不完全清楚,但这里是一个基本的游乐场示例:
import Combine
import Foundation
class CombineNotificationSender {
var message : String
init(_ messageToSend: String) {
message = messageToSend
}
static let combineNotification = Notification.Name("CombineNotification")
}
class CombineNotificationReceiver {
var cancelSet: Set<AnyCancellable> = []
init() {
NotificationCenter.default.publisher(for: CombineNotificationSender.combineNotification)
.compactMap{$0.object as? CombineNotificationSender}
.map{$0.message}
.sink() {
[weak self] message in
self?.handleNotification(message)
}
.store(in: &cancelSet)
}
func handleNotification(_ message: String) {
print(message)
}
}
let receiver = CombineNotificationReceiver()
let sender = CombineNotificationSender("Message from sender")
NotificationCenter.default.post(name: CombineNotificationSender.combineNotification, object: sender)
sender.message = "Another message from sender"
NotificationCenter.default.post(name: CombineNotificationSender.combineNotification, object: sender)对于某些用例,您也可以使它成为一个只使用组合解决方案而不使用通知。
import Combine
import Foundation
class CombineMessageSender {
@Published var message : String?
}
class CombineMessageReceiver {
private var cancelSet: Set<AnyCancellable> = []
init(_ publisher: AnyPublisher<String?, Never>) {
publisher
.compactMap{$0}
.sink() {
self.handleNotification($0)
}
.store(in: &cancelSet)
}
func handleNotification(_ message: String) {
print(message)
}
}
let sender = CombineMessageSender()
let receiver = CombineMessageReceiver(sender.$message.eraseToAnyPublisher())
sender.message = "Message from sender"
sender.message = "Another message from sender"https://stackoverflow.com/questions/58559908
复制相似问题