NSNotificationCenter addObserver в Swift

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

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

Ответ 1

Он такой же, как 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 и Swift 5:

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

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

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

Посмотрите Ссылку класса NSNotificationCenter, Взаимодействие с API Objective C

Ответ 2

Swift 4.0 и Xcode 9. 0+:

Отправить (Post) уведомление:

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

Отправить (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
}

Ответ 3

Swift 3.0 в Xcode 8

Swift 3.0 заменил многие "строчно типизированные" 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 и т.д.

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

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

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

Ответ 4

Хорошим способом сделать это является использование 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)

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

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

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

    NotificationCenter.default.removeObserver(observer)

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

Ответ 5

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

от iOS 9 и OS X 10.11. Больше не нужно, чтобы наблюдатель NSNotificationCenter отменял свою регистрацию при освобождении. больше информации

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

Ответ 6

Передача данных с использованием 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

Пользовательская информация теперь принимает [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)

Ответ 7

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

Ответ 8

В быстром 2.2 - XCode 7.3 мы используем #selector для NSNotificationCenter

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

Ответ 9

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

Исх.

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

}

Ответ 10

В быстром 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

NSNotificationCenter добавить синтаксис наблюдателя в Swift 4.0 для iOS 11

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

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

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

Ответ 12

Swift 5 & Xcode 10.2:

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

Ответ 13

В Свифт 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)
    }

}