ios Swift 中的 NSNotificationCenter addObserver

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24049020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:28:34  来源:igfitidea点击:

NSNotificationCenter addObserver in Swift

iosswiftnsnotificationcenter

提问by Berry Blue

How do you add an observer in Swift to the default notification center? I'm trying to port this line of code that sends a notification when the battery level changes.

如何将 Swift 中的观察者添加到默认通知中心?我正在尝试移植这行代码,当电池电量发生变化时发送通知。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];

回答by Renish Dadhaniya

Swift 4.0 & Xcode 9.0+:

Swift 4.0 和 Xcode 9.0+:

Send(Post) Notification:

发送(发布)通知:

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

OR

或者

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])

Receive(Get) Notification:

接收(获取)通知:

NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

Function-Method handler for received Notification:

接收通知的函数方法处理程序:

@objc func methodOfReceivedNotification(notification: Notification) {}

Swift 3.0 & Xcode 8.0+:

Swift 3.0 和 Xcode 8.0+:

Send(Post) Notification:

发送(发布)通知:

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

Receive(Get) Notification:

接收(获取)通知:

NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

Method handler for received Notification:

接收通知的方法处理程序:

func methodOfReceivedNotification(notification: Notification) {
  // Take Action on Notification
}

Remove Notification:

删除通知:

deinit {
  NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil)
}

Swift 2.3 & Xcode 7:

斯威夫特 2.3 和 Xcode 7:

Send(Post) Notification

发送(发布)通知

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

Receive(Get) Notification

接收(获取)通知

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil)

Method handler for received Notification

接收通知的方法处理程序

func methodOfReceivedNotification(notification: NSNotification){
  // Take Action on Notification
}




For historic Xcode versions...

对于历史悠久的 Xcode 版本...





Send(Post) Notification

发送(发布)通知

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

Receive(Get) Notification

接收(获取)通知

NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil)

Remove Notification

删除通知

NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed

Method handler for received Notification

接收通知的方法处理程序

func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

Annotate either the class or the target method with @objc

使用 @objc 注释类或目标方法

@objc private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

// Or

dynamic private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

回答by Connor

It's the same as the Objective-C API, but uses Swift's syntax.

它与 Objective-C API 相同,但使用 Swift 的语法。

Swift 4.2 & Swift 5:

斯威夫特 4.2 和斯威夫特 5:

NotificationCenter.default.addObserver(
    self,
    selector: #selector(self.batteryLevelChanged),
    name: UIDevice.batteryLevelDidChangeNotification,
    object: nil)

If your observer does not inherit from an Objective-C object, you must prefix your method with @objcin order to use it as a selector.

如果您的观察者不是从 Objective-C 对象继承的,则您必须为您的方法添加前缀@objc以将其用作选择器。

@objc private func batteryLevelChanged(notification: NSNotification){     
    //do stuff using the userInfo property of the notification object
}

See NSNotificationCenter Class Reference, Interacting with Objective-C APIs

请参阅NSNotificationCenter 类参考与 Objective-C API 交互

回答by Jon Colverson

A nice way of doing this is to use the addObserver(forName:object:queue:using:)method rather than the addObserver(_:selector:name:object:)method that is often used from Objective-C code. The advantage of the first variant is that you don't have to use the @objcattribute on your method:

这样做的一个好方法是使用addObserver(forName:object:queue:using:)方法而不是addObserver(_:selector:name:object:)经常在 Objective-C 代码中使用的方法。第一个变体的优点是您不必@objc在方法上使用该属性:

    func batteryLevelChanged(notification: Notification) {
        // do something useful with this information
    }

    let observer = NotificationCenter.default.addObserver(
        forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
        object: nil, queue: nil,
        using: batteryLevelChanged)

and you can even just use a closure instead of a method if you want:

如果需要,您甚至可以只使用闭包而不是方法:

    let observer = NotificationCenter.default.addObserver(
        forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
        object: nil, queue: nil) { _ in print("") }

You can use the returned value to stop listening for the notification later:

您可以使用返回值稍后停止监听通知:

    NotificationCenter.default.removeObserver(observer)

There used to be another advantage in using this method, which was that it doesn't require you to use selector strings which couldn't be statically checked by the compiler and so were fragile to breaking if the method is renamed, but Swift 2.2 and later include #selectorexpressionsthat fix that problem.

过去使用这种方法还有另一个优势,那就是它不需要你使用编译器无法静态检查的选择器字符串,因此如果重命名方法,很容易被破坏,但是 Swift 2.2 和稍后包含解决该问题的#selector表达式

回答by Jeffrey Fulton

Swift 3.0 in Xcode 8

Xcode 8 中的 Swift 3.0

Swift 3.0 has replaced many "stringly-typed" APIs with struct"wrapper types", as is the case with NotificationCenter. Notifications are now identified by a struct Notfication.Namerather than by String. See the Migrating to Swift 3 guide.

Swift 3.0 已经用struct“包装器类型”替换了许多“字符串类型”的 API ,就像 NotificationCenter 的情况一样。通知现在由 标识struct Notfication.Name而不是由标识String。请参阅迁移到 Swift 3 指南

Previoususage:

以前的用法:

// 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)

New Swift 3.0 usage:

新的 Swift 3.0 用法:

// 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)

All of the system notification types are now defined as static constants on Notification.Name; i.e. .UIDeviceBatteryLevelDidChange, .UIApplicationDidFinishLaunching, .UITextFieldTextDidChange, etc.

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

You can extend Notification.Namewith your own custom notifications in order to stay consistent with the system notifications:

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

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

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

回答by Warif Akhand Rishi

  1. Declare a notification name

    extension Notification.Name {
        static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
    }
    
  2. You can add observer in two ways:

    Using Selector

    NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: .purchaseDidFinish, object: nil)
    
    @objc func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
    

    or using block

    NotificationCenter.default.addObserver(forName: .purchaseDidFinish, object: nil, queue: nil) { [weak self] (notification) in
        guard let strongSelf = self else {
            return
        }
    
        strongSelf.myFunction(notification: notification)
    }
    
    func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
    
  3. Post your notification

    NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
    
  1. 声明一个通知名称

    extension Notification.Name {
        static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
    }
    
  2. 您可以通过两种方式添加观察者:

    使用 Selector

    NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: .purchaseDidFinish, object: nil)
    
    @objc func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
    

    或使用 block

    NotificationCenter.default.addObserver(forName: .purchaseDidFinish, object: nil, queue: nil) { [weak self] (notification) in
        guard let strongSelf = self else {
            return
        }
    
        strongSelf.myFunction(notification: notification)
    }
    
    func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
    
  3. 发布您的通知

    NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
    

from iOS 9 and OS X 10.11. It is no longer necessary for an NSNotificationCenter observer to un-register itself when being deallocated. more info

从 iOS 9 和 OS X 10.11。NSNotificationCenter 观察者在被释放时不再需要取消注册自己。更多信息

For a blockbased implementation you need to do a weak-strong dance if you want to use selfinside the block. more info

对于block基于实现的实现,如果您想self在块内使用,则需要进行弱-强舞蹈。更多信息

Block based observers need to be removed more info

需要删除基于块的观察者更多信息

let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)

回答by Sahil

Pass Data using NSNotificationCenter

使用 NSNotificationCenter 传递数据

You can also pass data using NotificationCentre in swift 3.0 and NSNotificationCenter in swift 2.0.

您还可以使用 swift 3.0 中的 NotificationCentre 和 swift 2.0 中的 NSNotificationCenter 传递数据。

Swift 2.0 Version

斯威夫特 2.0 版本

Pass info using userInfo which is a optional Dictionary of type [NSObject : AnyObject]?

使用 userInfo 传递信息,它是 [NSObject : AnyObject] 类型的可选字典?

let imageDataDict:[String: UIImage] = ["image": image]

// Post a notification
 NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil, userInfo: imageDataDict)

// Register to receive notification in your class
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: notificationName, object: nil)

// handle notification
func showSpinningWheel(notification: NSNotification) {
  if let image = notification.userInfo?["image"] as? UIImage {
  // do something with your image   
  }
}

Swift 3.0 Version

斯威夫特 3.0 版本

The userInfo now takes [AnyHashable:Any]? as an argument, which we provide as a dictionary literal in Swift

userInfo 现在采用 [AnyHashable:Any]? 作为参数,我们在 Swift 中将其作为字典文字提供

let imageDataDict:[String: UIImage] = ["image": image]

// post a notification
 NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict) 
// `default` is now a property, not a method call

// Register to receive notification in your class
NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)

// handle notification
func showSpinningWheel(_ notification: NSNotification) {

  if let image = notification.userInfo?["image"] as? UIImage {
  // do something with your image   
  }
}

Source pass data using NotificationCentre(swift 3.0) and NSNotificationCenter(swift 2.0)

使用 NotificationCentre(swift 3.0) 和 NSNotificationCenter(swift 2.0)传递数据

回答by swiftBoy

In Swift 5

斯威夫特 5

Let's say if want to Receive Data from ViewControllerB to ViewControllerA

假设想从 ViewControllerB 接收数据到 ViewControllerA

ViewControllerA (Receiver)

ViewControllerA(接收器)

import UIKit

class ViewControllerA: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()

        //MARK: - - - - - Code for Passing Data through Notification Observer - - - - -
        // add observer in controller(s) where you want to receive data
        NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
    }

    //MARK: - - - - - Method for receiving Data through Post Notificaiton - - - - -
    @objc func methodOfReceivedNotification(notification: Notification) {
        print("Value of notification : ", notification.object ?? "")
    }
}


ViewControllerB (Sender)

ViewControllerB(发送方)

import UIKit

class ViewControllerB: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //MARK: - - - - - Set data for Passing Data Post Notification - - - - -
        let objToBeSent = "Test Message from Notification"
        NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
    }

}

回答by Deepak Thakur

In swift 2.2 - XCode 7.3, we use #selectorfor NSNotificationCenter

在 swift 2.2 - XCode 7.3 中,我们使用#selectorforNSNotificationCenter

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)

回答by Pankaj Jangid

We should remove notification also.

我们也应该删除通知。

Ex.

前任。

deinit 
{
  NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil)

}

回答by leanne

I'm able to do one of the following to successfully use a selector - withoutannotating anything with @objc:

我可以执行以下操作之一来成功使用选择器 -无需使用 @objc 注释任何内容:

NSNotificationCenter.defaultCenter().addObserver(self,
    selector:"batteryLevelChanged:" as Selector,
    name:"UIDeviceBatteryLevelDidChangeNotification",
    object:nil)    

OR

或者

let notificationSelector: Selector = "batteryLevelChanged:"

NSNotificationCenter.defaultCenter().addObserver(self,
    selector: notificationSelector,
    name:"UIDeviceBatteryLevelDidChangeNotification",
    object:nil)    

My xcrun version shows Swift 1.2, and this works on Xcode 6.4 and Xcode 7 beta 2 (which I thought would be using Swift 2.0):

我的 xcrun 版本显示 Swift 1.2,这适用于 Xcode 6.4 和 Xcode 7 beta 2(我认为会使用 Swift 2.0):

$xcrun swift --version

Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)