【问题标题】:NotificationCenter issue on Swift 3 [duplicate]Swift 3 上的 NotificationCenter 问题 [重复]
【发布时间】:2016-11-07 08:46:33
【问题描述】:

我正在学习 Swift 3,我正在尝试使用 NSNotificationCenter。这是我的代码:

func savePost(){
    let postData = NSKeyedArchiver.archivedData(withRootObject: _loadedpost)
    UserDefaults.standard().object(forKey: KEY_POST)
}
func loadPost(){
    if let postData = UserDefaults.standard().object(forKey: KEY_POST) as? NSData{
        if let postArray = NSKeyedUnarchiver.unarchiveObject(with: postData as Data) as? [Post]{
                _loadedpost = postArray
        }
    }
    //codeerror
    NotificationCenter.default().post(NSNotification(name: "loadedPost" as NSNotification.Name, object: nil) as Notification)
}

这是观察者:

override func viewDidLoad() {
    super.viewDidLoad()
//codeerorr
    NotificationCenter.default().addObserver(self, selector: Selector(("onPostLoaded")), name: "loadedPost", object: nil)
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

它总是给我错误“信号 SIGBRT”。当我尝试在观察者中更改名称时,这不是错误,但显然它没有显示任何内容。我该如何解决这个问题?

【问题讨论】:

标签: ios swift3 notificationcenter


【解决方案1】:

斯威夫特 3 & 4

Swift 3 和现在的 Swift 4 已经用struct“包装器类型”替换了许多“字符串类型”API,NotificationCenter 就是这种情况。通知现在由struct Notfication.Name 而不是String 标识。有关更多详细信息,请参阅现在的旧版 Migrating to Swift 3 guide

Swift 2.2 用法:

// Define identifier
let notificationIdentifier: String = "NotificationIdentifier"

// Register to receive notification
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name: notificationIdentifier, object: nil)

// Post a notification
NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil)

Swift 3 & 4 用法:

// Define identifier
let notificationName = Notification.Name("NotificationIdentifier")

// Register to receive notification
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil)

// Post notification
NotificationCenter.default.post(name: notificationName, object: nil)

// Stop listening notification
NotificationCenter.default.removeObserver(self, name: notificationName, object: nil)

所有系统通知类型现在都定义为Notification.Name 上的静态常量;即.UIApplicationDidFinishLaunching.UITextFieldTextDidChange

您可以使用自己的自定义通知扩展Notification.Name,以便与系统通知保持一致:

// Definition:
extension Notification.Name {
    static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}

// Usage:
NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)

Swift 4.2 用法:

与 Swift 4 相同,只是现在系统通知名称是 UIApplication 的一部分。因此,为了与系统通知保持一致,您可以使用自己的自定义通知扩展 UIApplication 而不是 Notification.Name :

// Definition:
UIApplication {
    public static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}

// Usage:
NotificationCenter.default.post(name: UIApplication.yourCustomNotificationName, object: nil)

【讨论】:

  • 新的 Swift 3.0 用法中的参数呢?我不知道如何解决这个问题。我总是收到一个致命错误“无法识别的选择器发送到实例...”
  • @rmnblm 你能发布一些示例代码吗?谢谢!
  • default 似乎被严格解释为 Xcode 8 GM 种子中的关键字。
  • @Bobjt 你能解释更多吗?这段代码不再起作用了吗?
  • @Jeffrey Fulton,看来我说得太早了。通过其他 Swift 3 代码更改最终使编译器对 NotificationCenter.default 感到满意。很抱歉误报。
【解决方案2】:

通知似乎再次更改(2016 年 10 月)。

//注册接收通知

NotificationCenter.default.addObserver(self, selector: #selector(yourClass.yourMethod), name: NSNotification.Name(rawValue: "yourNotificatioName"), object: nil)

//发布通知

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "yourNotificationName"), object: nil)

【讨论】:

  • 您是否按照我上面的回答尝试使用Notification 代替NSNotification?这两个类是“桥接的”,这意味着它们可以互换使用。更多信息在developer.apple.com/reference/foundation/…的“Swift Foundation Overlay”部分中@
【解决方案3】:

对于所有在 Swift 3 或 Swift 4 中纠结于#selector 的人,这里有一个完整的代码示例:

// WE NEED A CLASS THAT SHOULD RECEIVE NOTIFICATIONS
    class MyReceivingClass {

    // ---------------------------------------------
    // INIT -> GOOD PLACE FOR REGISTERING
    // ---------------------------------------------
    init() {
        // WE REGISTER FOR SYSTEM NOTIFICATION (APP WILL RESIGN ACTIVE)

        // Register without parameter
        NotificationCenter.default.addObserver(self, selector: #selector(MyReceivingClass.handleNotification), name: .UIApplicationWillResignActive, object: nil)

        // Register WITH parameter
        NotificationCenter.default.addObserver(self, selector: #selector(MyReceivingClass.handle(withNotification:)), name: .UIApplicationWillResignActive, object: nil)
    }

    // ---------------------------------------------
    // DE-INIT -> LAST OPTION FOR RE-REGISTERING
    // ---------------------------------------------
    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    // either "MyReceivingClass" must be a subclass of NSObject OR selector-methods MUST BE signed with '@objc'

    // ---------------------------------------------
    // HANDLE NOTIFICATION WITHOUT PARAMETER
    // ---------------------------------------------
    @objc func handleNotification() {
        print("RECEIVED ANY NOTIFICATION")
    }

    // ---------------------------------------------
    // HANDLE NOTIFICATION WITH PARAMETER
    // ---------------------------------------------
    @objc func handle(withNotification notification : NSNotification) {
        print("RECEIVED SPECIFIC NOTIFICATION: \(notification)")
    }
}

在这个例子中,我们尝试从 AppDelegate 获取 POST(所以在 AppDelegate 中实现这个):

// ---------------------------------------------
// WHEN APP IS GOING TO BE INACTIVE
// ---------------------------------------------
func applicationWillResignActive(_ application: UIApplication) {

    print("POSTING")

    // Define identifiyer
    let notificationName = Notification.Name.UIApplicationWillResignActive

    // Post notification
    NotificationCenter.default.post(name: notificationName, object: nil)
}

【讨论】:

  • 很好,彻底的答案。快速提问。我知道在 Objective-C 中,我们需要在离开视图(或发生坏事)时对移除观察者保持偏执。在 Swift3 中仍然是这种情况吗?我之所以问,是因为我没有看到很多其他答案提到这一点,而您明确说明了这一点。
  • 我不知道,它是否像在 Objective-C 中一样重要,但总的来说,我认为在不需要通知时关注注销是一种好习惯此外。您注册,当您需要收到通知时,您重新注册,当您不再需要它时。
  • 我现在可以确认解雇仍然很重要。 :) 回想起来似乎很明显,但如果你不解雇观察者,你就会冒着让多个观察者开火的风险。所以记得在 Swift 中解散,否则会发生坏事!
  • 这是帮助我理解的完美答案!
【解决方案4】:

我想它又变了。

在 Xcode 8.2 中发布此作品。

NotificationCenter.default.post(Notification(name:.UIApplicationWillResignActive)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    相关资源
    最近更新 更多