首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >合并:从带有选择器的Notification到Notification

合并:从带有选择器的Notification到Notification
EN

Stack Overflow用户
提问于 2019-10-25 13:53:25
回答 2查看 11.1K关注 0票数 15

我已经看到了如何使用来自某些NotificationCenter代码的发布者来进行转换,但是还没有看到如何实现这样的转换:

代码语言:javascript
复制
        NotificationCenter.default.addObserver(
        self,
        selector: #selector(notCombine),
        name: NSNotification.Name(rawValue: "notCombine"),
        object: nil
    )

我已经看到这是作为发行者提供的,但是我selector没有,我不知道该为它做什么:

代码语言:javascript
复制
        NotificationCenter.default.publisher(
        for: Notification.Name(rawValue: "notCombine")
    )

有人知道吗?谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-27 22:46:02

你说的“我没有选择器”是对的,因为这是一半的道理。您可以在没有选择器的情况下从通知中心接收通知。

要点的另一半是,您可以将处理通知的逻辑向上推到组合管道中,这样,如果完全到达管道,正确的结果就会弹出管道的末尾。

老式的方式

假设我有一个Card视图,当通过发布通知来监听它时,它会发出虚拟尖叫:

代码语言:javascript
复制
static let tapped = Notification.Name("tapped")
@objc func tapped() {
    NotificationCenter.default.post(name: Self.tapped, object: self)
}

现在,为了示例的目的,假设游戏在收到这些通知之一时感兴趣的是发布通知的卡片的name属性的字符串值。如果我们用传统的方法去做,那么获取信息是一个两阶段的过程。首先,我们必须登记才能收到通知:

代码语言:javascript
复制
NotificationCenter.default.addObserver(self, 
    selector: #selector(cardTapped), name: Card.tapped, object: nil)

然后,当我们收到通知时,我们必须查看它的object确实是一张卡片,如果是的话,获取它的name属性并使用它做一些事情:

代码语言:javascript
复制
@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操作符来获取它。结果如下:

代码语言:javascript
复制
let cardTappedCardNamePublisher = 
    NotificationCenter.default.publisher(for: Card.tapped)
        .compactMap {$0.object as? Card}
        .map {$0.name}

假设cardTappedCardNamePublisher是视图控制器的实例属性。然后,我们现在拥有的是一个实例属性,如果卡片发布tapped通知,否则什么也不做,它就会发布一个字符串。

当我说逻辑被推上管道时,你明白我的意思吗?

那么,我们将如何安排接收从管道末端出来的东西呢?我们需要一个水槽:

代码语言:javascript
复制
let sink = self.cardTappedCardNamePublisher.sink {
    print($0) // the string name of a card
}

如果您尝试,您将看到,我们现在有一种情况,每次用户点击一张卡,卡的名字是打印出来的。这是我们先前的寄存器-一个观察者-和-一个选择器方法的组合。

票数 36
EN

Stack Overflow用户

发布于 2019-10-27 21:52:02

用例并不完全清楚,但这里是一个基本的游乐场示例:

代码语言:javascript
复制
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)

对于某些用例,您也可以使它成为一个只使用组合解决方案而不使用通知。

代码语言:javascript
复制
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"
票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58559908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档