Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 合并:从通知中心addObserver和选择器转到通知发布者_Swift_Combine - Fatal编程技术网

Swift 合并:从通知中心addObserver和选择器转到通知发布者

Swift 合并:从通知中心addObserver和选择器转到通知发布者,swift,combine,Swift,Combine,我已经看到了如何使用某个通知中心的发布者将其转换为组合,但还没有看到如何为以下内容进行转换: NotificationCenter.default.addObserver( self, selector: #selector(notCombine), name: NSNotification.Name(rawValue: "notCombine"), object: nil ) 我已经看到这是作为一个发布者

我已经看到了如何使用某个
通知中心的发布者将其转换为组合,但还没有看到如何为以下内容进行转换:

        NotificationCenter.default.addObserver(
        self,
        selector: #selector(notCombine),
        name: NSNotification.Name(rawValue: "notCombine"),
        object: nil
    )
我已经看到这是作为一个发布者提供的,但是我没有一个
选择器
,也不知道该怎么做:

        NotificationCenter.default.publisher(
        for: Notification.Name(rawValue: "notCombine")
    )

有人知道吗?谢谢

用例并不完全清楚,但这里有一个示例:

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)
导入联合收割机
进口基金会
类组合化发送器{
var消息:字符串
init(uMessageToSend:String){
message=messageToSend
}
静态let combineNotification=Notification.Name(“combineNotification”)
}
类组合化接收机{
var cancelSet:Set=[]
init(){
NotificationCenter.default.publisher(用于:CombineNotificationSender.combineNotification)
.compactMap{$0.object as?CombineNotificationSender}
.map{$0.message}
.sink(){
[弱自我]信息输入
自我?手动通知(信息)
}
.store(在:&cancelSet中)
}
func handleNotification(umessage:String){
打印(信息)
}
}
let receiver=CombineNotificationReceiver()
let sender=CombineNotificationSender(“来自发件人的消息”)
NotificationCenter.default.post(名称:CombineNotificationSender.combineNotification,对象:sender)
sender.message=“来自发件人的另一封邮件”
NotificationCenter.default.post(名称:CombineNotificationSender.combineNotification,对象: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"
导入联合收割机
进口基金会
类组合消息发送程序{
@已发布的var消息:字符串?
}
类组合消息接收器{
私有变量cancelSet:Set=[]
init(upublisher:AnyPublisher){
出版商
.compactMap{$0}
.sink(){
自我手动通知($0)
}
.store(在:&cancelSet中)
}
func handleNotification(umessage:String){
打印(信息)
}
}
let sender=CombineMessageSender()
let receiver=CombineMessageReceiver(发送方$message.橡皮擦到任何发布方())
sender.message=“来自发件人的邮件”
sender.message=“来自发件人的另一封邮件”
你说“我没有选择器”是对的,因为这是问题的一半。您可以使用Combine从通知中心接收通知,而无需使用选择器

这一点的另一半是,您可以将处理通知的逻辑向上推到合并管道中,这样,如果通知到达您手中,正确的结果就会从管道末端弹出

老式的方式 假设我有一个卡片视图,当通过发布通知点击它时,它会发出一声虚拟尖叫:

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)
然后,当我们收到通知时,我们必须查看其
对象
是否确实是一张卡,如果是,则获取其
名称
属性并对其进行处理:

@objc func cardTapped(_ n:Notification) {
    if let card = n.object as? Card {
        let name = card.name
        print(name) // or something
    }
}
联合收割机 现在让我们使用Combine框架做同样的事情。我们通过调用其
publisher
方法从通知中心获取发布者。但我们不会就此止步。如果
对象
不是卡,我们不希望收到通知,因此我们使用
compactMap
操作符将其安全地投射到卡上(如果它不是卡,管道将停止,就像什么都没有发生一样)。我们只需要卡的
名称
,因此我们使用
映射
操作符来获取它。结果如下:

let cardTappedCardNamePublisher = 
    NotificationCenter.default.publisher(for: Card.tapped)
        .compactMap {$0.object as? Card}
        .map {$0.name}
假设
cardTappedCardNamePublisher
是视图控制器的实例属性。那么我们现在拥有的是一个实例属性,如果一张卡发布了
点击的
通知,它将发布一个字符串,否则什么也不做

你明白我说的逻辑被推上管道是什么意思吗

那么,我们将如何安排接收从管道末端输出的内容呢?我们可以用水槽:

let sink = self.cardTappedCardNamePublisher.sink {
    print($0) // the string name of a card
}

如果你尝试一下,你会发现我们现在有一种情况,每次用户点击一张卡片,卡片的名称就会被打印出来。这是我们早期的register-an-observer-with-a-selector方法的等效组合。

谢谢,我将尝试实现这一点!我还将尝试在此Q中添加另一个悬赏,以向您提供悬赏,当另一个Viewcontroller中的publisher和订阅者位于另一个Viewcontroller中时,如何使用此悬赏?就像我们对通知中心所做的那样?你能告诉我如何在Comine中处理这种情况吗->我有一个包含内容视图的VC(比如主VC),其中不时包含另一个VC的内容视图,当用户使用combine在内容视图中点击VC上的按钮时,主VC如何得到通知?本讨论与我的这个问题和答案无关。请把你的问题当作真正的问题来问。