NSVotificationCenter在Swift中添加了addObserver

时间:2014-06-04 23:02:05

标签: ios swift nsnotificationcenter

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

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

14 个答案:

答案 0 :(得分:717)

Swift 4.0& Xcode 9.0 +:

发送(发布)通知:

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

<强> OR

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&amp; Xcode 8.0 +:

发送(发布)通知:

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&amp; Xcode 7:

发送(发布)通知

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版本......



发送(发布)通知

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
}

答案 1 :(得分:416)

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

NSNotificationCenter.defaultCenter().addObserver(
    self,
    selector: #selector(batteryLevelChanged:),
    name: UIDeviceBatteryLevelDidChangeNotification,
    object: nil)

斯威夫特3:

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

Swift 4.2&amp;斯威夫特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 Class ReferenceInteracting with Objective-C APIs

答案 2 :(得分:41)

Xcode 8中的Swift 3.0

Swift 3.0已经取代了许多&#34;串式打字&#34;具有struct&#34;包装类型&#34;的API,与NotificationCenter的情况一样。现在,通知由struct Notfication.Name而不是String标识。请参阅Migrating to Swift 3 guide

上一页用法:

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

答案 3 :(得分:40)

这样做的好方法是使用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 expressions来解决这个问题。

答案 4 :(得分:17)

  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(notificaiont: Notification) {
        print(notificaiont.object ?? "") //myObject
        print(notificaiont.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(notificaiont: notification)
    }
    
    func myFunction(notificaiont: Notification) {
        print(notificaiont.object ?? "") //myObject
        print(notificaiont.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
    
  3. 发布您的通知

    NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
    
  4.   来自iOS 9和OS X 10.11的

    。它不再是必需的   NSNotificationCenter观察者在进行时取消注册   释放。 more info

    对于基于block的实现,如果要在块内使用self,则需要进行弱强舞。 more info

答案 5 :(得分:8)

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

来源pass data using NotificationCentre(swift 3.0) and NSNotificationCenter(swift 2.0)

答案 6 :(得分:2)

我可以执行以下操作之一来成功使用选择器 - 没有使用@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)    

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

答案 7 :(得分:2)

在swift 2.2 - XCode 7.3中,我们使用#selector作为NSNotificationCenter

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

答案 8 :(得分:2)

我们也应该删除通知。

实施例

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

}

答案 9 :(得分:2)

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)

}

答案 10 :(得分:1)

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

答案 11 :(得分:1)

NSNotificationCenter Swift 4.0 中为 iOS 11 添加观察者语法

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

这是针对keyboardWillShow的通知名称类型。可以从可用选项

中选择其他类型

Selector的类型为@objc func,用于处理键盘的显示方式(这是您的用户功能)

答案 12 :(得分:1)

Swift 5

  

如果要从ViewControllerB接收数据到   ViewControllerA

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

}

答案 13 :(得分:0)

Swift 5和Xcode 10.2:

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