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
-
Объявить имя уведомления
extension Notification.Name {
static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
}
-
Вы можете добавить наблюдателя двумя способами:
Использование 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"]
}
-
Разместите ваше уведомление
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)
}
}