Comment ajouter un observateur dans Swift au centre de notification par défaut? J'essaie de porter cette ligne de code qui envoie une notification lorsque le niveau de la batterie change.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
C'est la même chose que l'API Objective-C, mais utilise la syntaxe de 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)
Swift 4.2:
NotificationCenter.default.addObserver(
self,
selector: #selector(self.batteryLevelChanged),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)
Si votre observateur n'hérite pas d'un objet Objective-C, vous devez préfixer votre méthode avec @objc
afin de l'utiliser comme sélecteur.
@objc private func batteryLevelChanged(notification: NSNotification){
//do stuff using the userInfo property of the notification object
}
Voir Référence de la classe NSNotificationCenter , Interaction avec les API Objective-C
Envoyer une notification (post):
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)
OU
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])
Recevoir la notification (Get):
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
Gestionnaire de méthodes de fonction pour la notification reçue:
@objc func methodOfReceivedNotification(notification: Notification) {}
Envoyer une notification (post):
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)
Recevoir la notification (Get):
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
Gestionnaire de méthodes pour la notification reçue:
func methodOfReceivedNotification(notification: Notification) {
// Take Action on Notification
}
Supprimer la notification:
deinit {
NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil)
}
Envoyer une notification (post)
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
Recevoir une notification
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil)
Gestionnaire de méthodes pour la notification reçue
func methodOfReceivedNotification(notification: NSNotification){
// Take Action on Notification
}
Pour les versions historiques de Xcode ...
Envoyer une notification (post)
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
Recevoir une notification
NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil)
Supprimer la notification
NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed
Gestionnaire de méthodes pour la notification reçue
func methodOfReceivedNotification(notification: NSNotification) {
// Take Action on Notification
}
Annotez la classe ou la méthode cible avec @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 a remplacé de nombreuses API "à typage strict" par struct
"types de wrapper", comme c'est le cas avec NotificationCenter. Les notifications sont maintenant identifiées par un struct Notfication.Name
plutôt que par String
. Voir le guide Migration vers Swift 3 .
Utilisation précédente:
// 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)
Nouvelle utilisation de 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)
Tous les types de notification système sont maintenant définis en tant que constantes statiques sur Notification.Name
; c'est-à-dire .UIDeviceBatteryLevelDidChange
, .UIApplicationDidFinishLaunching
, .UITextFieldTextDidChange
, etc.
Vous pouvez étendre Notification.Name
avec vos propres notifications personnalisées afin de rester cohérent avec les notifications système:
// Definition:
extension Notification.Name {
static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}
// Usage:
NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)
Une bonne façon de procéder consiste à utiliser la méthode addObserver(forName:object:queue:using:)
plutôt que la méthode addObserver(_:selector:name:object:)
qui est souvent utilisée à partir de code Objective-C. L'avantage de la première variante est que vous n'avez pas à utiliser l'attribut @objc
sur votre méthode:
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)
et vous pouvez même simplement utiliser une fermeture au lieu d'une méthode si vous voulez:
let observer = NotificationCenter.default.addObserver(
forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
object: nil, queue: nil) { _ in print("????") }
Vous pouvez utiliser la valeur renvoyée pour arrêter d'écouter la notification ultérieurement:
NotificationCenter.default.removeObserver(observer)
L’utilisation de cette méthode présentait un autre avantage: elle ne nécessitait pas l’utilisation de chaînes de sélecteur qui ne pouvaient pas être vérifiées statiquement par le compilateur et étaient donc fragiles à la rupture si la méthode était renommée, mais Swift 2.2 et plus tard, inclure #selector
expressions qui résolvent ce problème.
Déclarer un nom de notification
extension Notification.Name {
static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
}
Vous pouvez ajouter observateur de deux manières:
Utiliser 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"]
}
ou en utilisant 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"]
}
Postez votre notificaion
NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
depuis iOS 9 et OS X 10.11. Il n'est plus nécessaire pour un NSNotificationCenter observateur pour se désinscrire lui-même lorsqu’il est désalloué. Plus d'informations
Pour une implémentation basée sur block
, vous devez faire une danse faible-forte si vous voulez utiliser self
à l'intérieur du bloc. Plus d'informations
Pass Data using NSNotificationCenter
Vous pouvez également transmettre des données à l'aide de NotificationCentre dans Swift 3.0 et de NSNotificationCenter dans Swift 2.0.
Swift 2.0 Version
Passer les informations en utilisant userInfo qui est un dictionnaire facultatif de type [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 Version
Le userInfo prend maintenant [AnyHashable: Any]? comme argument, que nous fournissons sous forme de dictionnaire dans 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
}
}
Nous devrions également supprimer la notification.
Ex.
deinit
{
NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil)
}
Je peux effectuer l'une des opérations suivantes pour utiliser avec succès un sélecteur - sans annoter quoi que ce soit avec @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)
Ma version xcrun montre Swift 1.2, et cela fonctionne sur Xcode 6.4 et Xcode 7 beta 2 (je pensais que cela utiliserait Swift 2.0):
$xcrun Swift --version
Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)
Dans Swift 2.2 - XCode 7.3, nous utilisons #selector
pour NSNotificationCenter
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
Dans Swift 5
Disons que si vous voulez recevoir des données de ViewControllerB à ViewControllerA
ViewControllerA (récepteur)
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 (Sender)
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)
}
}
Dans Swift 3, Xcode 8.2: - vérification du niveau d'état de la batterie
//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 ajouter la syntaxe d'observateur dans Swift 4.0 pour iOS 11
NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
C'est pour le type de nom de notification keyboardWillShow. Un autre type peut être sélectionné parmi les options disponibles
le sélecteur est de type @objc func et gère le mode d'affichage du clavier (il s'agit de votre fonction utilisateur)
Swift 5 & Xcode 10.2:
NotificationCenter.default.addObserver(
self,
selector: #selector(batteryLevelDidChangeNotification),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)