web-dev-qa-db-fra.com

NSNotificationCenter addObserver dans Swift

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];
356
Berry Blue

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

401
Connor

Swift 4.0 et Xcode 9.0+:

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) {}

Swift 3.0 et Xcode 8.0+:

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)
}

Swift 2.3 & Xcode 7:

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
}
703
Renish Dadhaniya

Swift 3.0 dans Xcode 8

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)
40
Jeffrey Fulton

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.

37
Jon Colverson
  1. Déclarer un nom de notification

    extension Notification.Name {
        static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
    }
    
  2. 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"]
    }
    
  3. 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

15
Warif Akhand Rishi

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   
  }
}

Source transmettre des données à l'aide de NotificationCentre (Swift 3.0) et NSNotificationCenter (Swift 2.0)

7
Sahil

Nous devrions également supprimer la notification.

Ex.

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

}
2
Pankaj Jangid

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)
2
leanne

Dans Swift 2.2 - XCode 7.3, nous utilisons #selector pour NSNotificationCenter

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

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)
    }

}
1
swiftBoy

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
    }
1
Dhruv

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)

0
Ashim Dahal

Swift 5 & Xcode 10.2:

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