Swift 3协议的可选绑定

时间:2017-04-17 19:23:31

标签: ios swift swift3 nsnotificationcenter swift-protocols

编辑已解决,请参阅下面的解决方案。我仍然很好奇为什么它有效,或许你的解决方案可以解释这个?

我使用NotificationCenter发布通知传递对象。

我的目标是,如果notification.object符合某个protocol,我可以自行解包。

问题在于测试,展开证明是不成功的,我不知道为什么。

一系列对象(有时是enum,有时是struct),他们遵守NotificationsPipelineProtocol并将这些对象与通知一起发送给订阅这些通知的接收对象

因此,例如,如果我将ReleaseNote传递给Notifications Pipeline,我会让它订阅协议:

enum ReleaseNote: Float, NotificationsPipelineProtocol {
    ...

当我想发布NotificationCenter时,为订阅NotificationsPipelineProtocol的所有项目编写的扩展函数被调用:

    // finishing task, wants to post completion
    ...
        self.postCompletion()
    ...

调用此功能

    func postCompletion() {
        NotificationCenter.default.post(name: self.completionNotificationName, object: self)
    }

我保证使用此功能正确接收:

@objc private func didReceiveNotificationCompletion(_ notification : Notification) {

    guard let completedNotification = notification.object as? NotificationsPipelineProtocol else {
        return
    }

但上面的guard语句没有解包并绑定可选项,因为return已执行。

我已将notification.object打印到控制台,并保证它实际上已接收到预期的对象。

你可能知道为什么它不会解开?

2 个答案:

答案 0 :(得分:1)

我已经通过将对象的访问权限从对象替换为userInfo来解决它。

我不完全确定为什么会这样,但确实有效。

发布对象

    func postCompletion() {
        NotificationCenter.default.post(name: self.completionNotificationName, object: nil, userInfo: ["pipelineItem": self])
    }

检索对象

    guard let userInfo = notification.userInfo,
          let completedNotification = userInfo["pipelineItem"] as? NotificationsPipelineProtocol else {
        return
    }

答案 1 :(得分:0)

此工作流程应该没有任何问题,也许您正在观察/发送错误的对象?

以下是您尝试做的一个示例,您可以在游乐场中使用它来查看它是否有效。尝试将代码移动到一个操场/示例项目中,这是最简单的情况,直到找到失败点为止!

//: Playground - noun: a place where people can play

import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

protocol NotificationsPipelineProtocol {

}

class TestObserver: NotificationsPipelineProtocol {

    init() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(notificationFired(_:)),
                                               name: nil,
                                               object: self)
    }

    dynamic func notificationFired(_ notification: Notification) {
        guard let object = notification.object as? NotificationsPipelineProtocol else {
            return
        }

        print("success")
    }

    func fireNotification() {
        NotificationCenter.default.post(name: Notification.Name(rawValue: "test"), object: self)
    }

}

let observer = TestObserver()
observer.fireNotification()