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
выражения чтобы исправить эту проблему.
-
объявить имя уведомления
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"] }
-
пост ваш 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, который обрабатывает, как клавиатура покажет (это ваша функция пользователя )