NSNotificationCenter addObserver in Swift

后端 未结 14 1994
难免孤独
难免孤独 2020-11-22 05:23

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.

相关标签:
14条回答
  • 2020-11-22 06:08

    I'm able to do one of the following to successfully use a selector - without annotating anything with @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 --version
    
    Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)
    
    0 讨论(0)
  • 2020-11-22 06:10

    In swift 2.2 - XCode 7.3, we use #selector for NSNotificationCenter

     NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
    
    0 讨论(0)
  • 2020-11-22 06:10

    Swift 5 & Xcode 10.2:

    NotificationCenter.default.addObserver(
                self,
                selector: #selector(batteryLevelDidChangeNotification),
                name: UIDevice.batteryLevelDidChangeNotification,
                object: nil)
    
    0 讨论(0)
  • 2020-11-22 06:11

    Swift 3.0 in Xcode 8

    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.Name rather than by String. See the Migrating to Swift 3 guide.

    Previous usage:

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

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

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

    // Definition:
    extension Notification.Name {
        static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
    }
    
    // Usage:
    NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)
    
    0 讨论(0)
  • 2020-11-22 06:12

    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+:

    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:

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



    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 private func methodOfReceivedNotification(notification: NSNotification) {
      // Take Action on Notification
    }
    
    // Or
    
    dynamic private func methodOfReceivedNotification(notification: NSNotification) {
      // Take Action on Notification
    }
    
    0 讨论(0)
  • 2020-11-22 06:12

    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 @objc attribute on your method:

        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("                                                                    
    0 讨论(0)
提交回复
热议问题