NSNotificationCenter addObserver在Swift

如何在默认的通知中心中添加一个观察者?我试图移植这行代码,当电池电量变化时发送通知。

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

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

Swift 4.2 &斯威夫特5:

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

如果你的观察器没有继承自Objective-C对象,你必须给你的方法加上@objc前缀,以便将它用作选择器。

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

参见NSNotificationCenter类引用与Objective-C api交互

Swift 4.0 &Xcode 9.0 +:

发送(Post)通知:

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

< em >或< / em >

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

得到(获得)通知:

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

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

@objc func methodOfReceivedNotification(notification: Notification) {}

Swift 3.0 &Xcode 8.0 +:

发送(Post)通知:

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

得到(获得)通知:

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

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

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

删除通知:

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

Swift 2.3 &Xcode 7:

发送(Post)通知

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

得到(获得)通知

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

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

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


对于Xcode的历史版本



发送(Post)通知

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

得到(获得)通知

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

删除通知

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

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

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

用@objc注释类或目标方法

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


// Or


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

我能够做以下其中一个来成功使用选择器- 没有注释任何@objc:

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

let notificationSelector: Selector = "batteryLevelChanged:"


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

我的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)

一个很好的方法是使用addObserver(forName:object:queue:using:)方法,而不是在Objective-C代码中经常使用的addObserver(_:selector:name:object:)方法。第一个变量的优点是你不必在你的方法上使用@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)

如果你想,你甚至可以只使用闭包而不是方法:

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

你可以使用返回值来停止监听通知:

    NotificationCenter.default.removeObserver(observer)

以前使用这个方法还有另一个优点,那就是它不需要你使用选择器字符串,而选择器字符串不能被编译器静态检查,所以如果方法被重命名,就很容易被破坏,但Swift 2.2和以后的版本包含#selector表达式,解决了这个问题。

在swift 2.2 - XCode 7.3中,我们使用#selector代替NSNotificationCenter

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

Xcode 8中的Swift 3.0

Swift 3.0已经用struct“包装器类型”取代了许多“字符串类型”api, NotificationCenter也是如此。通知现在由struct Notfication.Name而不是String标识。参见迁移到Swift 3指南

以前的用法:

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

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

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

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


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

使用NSNotificationCenter传递数据

也支持通过swift 3.0中的NotificationCentre和swift 2.0中的NSNotificationCenter进行数据传递。

Swift 2.0版本

使用userInfo传递信息,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版本

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
}
}

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

我们也应该删除通知。

前女友。

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


}

在swift 3, Xcode 8.2:-检查电池状态水平

//Add observer
NotificationCenter.default.addObserver(self, selector: #selector(batteryStateDidChange), name: NSNotification.Name.UIDeviceBatteryStateDidChange, object: nil)




//Fired when battery level changes


func batteryStateDidChange(notification: NSNotification){
//perform manipulation here
}

NSNotificationCenter斯威夫特4.0中为iOS 11添加观察者语法

  NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

这是为keyboardWillShow通知名称类型。其他类型可以从可用选项中选择

选择器的类型是@objc func,它处理键盘的显示方式(这是你的用户函数)

  1. 声明通知名称

    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"]
    }
    

    或使用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"])
    

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

For a block based implementation you need to do a weak-strong dance if you want to use self inside the block. more info

Block based observers need to be removed more info

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

Swift 5 &Xcode 10.2:

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

斯威夫特5

我们说if想从ViewControllerB接收数据到 ViewControllerA < / p >

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(发送方)

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


}

Swift 5通知观察员

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(batteryLevelChanged), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
}


@objc func batteryLevelChanged(notification : NSNotification){
//do here code
}


override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: UIDevice.batteryLevelDidChangeNotification, object: nil)


}

这是一个非常简单的自定义通知观察者和post的例子

添加通知观察员

NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: Notification.Name("CustomeNotificationName"), object: nil)

添加选择器并处理观察者调用

@objc func myFunction(notification: Notification) {
    

//Write you code
}

在需要时发布通知(观察员)。

NotificationCenter.default.post(name: NSNotification.Name("CustomeNotificationName"), object: "Object", userInfo: ["key":"Value"])

注意:-当你离开屏幕时,你需要删除观察者。如。

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self);
}
  1. 创建一个objc函数,当通知被调用时执行该函数。
 @objc func reloadNotification(_ notification: Notification) {
tblview.reloadData()
}
  1. 在didload视图中添加通知观察者。
  NotificationCenter.default.addObserver(self, selector:#selector(reloadNotification(_:)), name: Notification.Name("reloadSideMenuDataNS"),object: nil)
  1. 将通知发布到想要调用函数的位置。
 NotificationCenter.default.post(name: Notification.Name("reloadSideMenuDataNS"), object: nil)
  1. 您可以删除您的通知在视图已消失下面。
 NotificationCenter.default.removeObserver(self, name: Notification.Name("reloadSideMenuDataNS"), object: nil)