NSNotificationCenter addObserver в Swift

Как добавить наблюдателя в Swift в Центр уведомлений по умолчанию? Я пытаюсь портировать эту строку кода, которая отправляет уведомление при изменении уровня заряда батареи.

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

11 ответов


это то же самое, что и API Objective-C, но использует синтаксис Swift.

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

или в Swift 3:

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

если ваш наблюдатель не наследует от Objective-C объекта, вы должны префикс вашего метода с @objc для того, чтобы использовать его в качестве селектора.

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

посмотреть Ссылка На Класс NSNotificationCenter, взаимодействие с Objective-C API


Swift 4.0 & Xcode 9.0+:

Отправить (Сообщение) Уведомление:

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

или

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

Отправить(Пост) Уведомление:

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:

Отправить (Сообщение) Уведомление

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

обработчик метода для received Уведомление

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
}

Swift 3.0 в Xcode 8

Swift 3.0 заменил многие" stringly-typed " API на struct "типы обертки", как в случае с NotificationCenter. Уведомления теперь идентифицируются с помощью struct Notfication.Name, а не String. Вижу переход на 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, etc.

вы можете продлить Notification.Name С вашими собственными пользовательскими уведомлениями, чтобы оставаться в соответствии с системными уведомлениями:

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

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

хороший способ сделать это-использовать addObserver(forName:object:queue:using:) метод, а не addObserver(_:selector:name:object:) метод, который часто используется из объективных-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)

и вы даже можете просто использовать закрытие вместо метода, если хотите:

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

вы можете использовать возвращенное значение, чтобы прекратить прослушивание уведомления позже:

    NotificationCenter.default.removeObserver(observer)

раньше было еще одно преимущество в использовании этого метода, которое заключалось в том, что он не требует использования строк селектора, которые не могли быть статически проверены компилятором и поэтому были хрупкими для взлома, если метод переименован, но Swift 2.2 и позже включают #selector выражения чтобы исправить эту проблему.


  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. пост ваш notificaion

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

из iOS 9 и OS X 10.11. Это больше не необходимо для NSNotificationCenter наблюдателя ООН-регистрируется при освободившему. подробнее

на block на основе реализации вам нужно сделать слабый сильный танец, если вы хотите использовать self внутри блока. подробнее


передача данных с помощью NSNotificationCenter

вы также можете передавать данные с помощью NotificationCentre в swift 3.0 и NSNotificationCenter в swift 2.0.

Swift 2.0 Версия

передать информацию с помощью 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)


Я могу сделать одно из следующих, чтобы успешно использовать селектор -без аннотирование чего-либо с помощью @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)

в swift 2.2-XCode 7.3 мы используем #selector на NSNotificationCenter

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

мы также должны удалить уведомление.

Ex.

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 добавить синтаксис наблюдателя в Swift 4.0 на iOS 11

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

Это для типа имени уведомления keyboardWillShow. Другой тип может быть выбран из существующих вариант

селектор имеет тип @objc func, который обрабатывает, как клавиатура покажет (это ваша функция пользователя )