wake-up-neo.com

NSNotificationCenter addObserver in Swift

Wie fügen Sie einen Beobachter in Swift zur Standardbenachrichtigungszentrale hinzu? Ich versuche, diese Codezeile zu portieren, die eine Benachrichtigung sendet, wenn sich der Batteriestand ändert.

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

Es ist dasselbe wie die Objective-C-API, verwendet jedoch die Syntax von 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)

Wenn Ihr Beobachter nicht von einem Objective-C-Objekt erbt, müssen Sie Ihrer Methode @objc voranstellen, um sie als Selektor verwenden zu können.

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

Siehe NSNotificationCenter-Klassenreferenz , Interaktion mit Objective-C-APIs

401
Connor

Swift 4.0 & Xcode 9.0+:

Senden (Post) Benachrichtigung:

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

ODER

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])

Empfangen (erhalten) Benachrichtigung:

NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

Funktionsmethodenhandler für empfangene Benachrichtigung:

@objc func methodOfReceivedNotification(notification: Notification) {}

Swift 3.0 & Xcode 8.0+:

Senden (Post) Benachrichtigung:

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

Empfangen (erhalten) Benachrichtigung:

NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

Methodenhandler für empfangene Benachrichtigung:

func methodOfReceivedNotification(notification: Notification) {
  // Take Action on Notification
}

Benachrichtigung entfernen:

deinit {
  NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil)
}

Swift 2.3 & Xcode 7:

Senden (Post) Benachrichtigung

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

Benachrichtigung erhalten (erhalten)

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil)

Methodenhandler für empfangene Benachrichtigung

func methodOfReceivedNotification(notification: NSNotification){
  // Take Action on Notification
}


Für historische Xcode-Versionen ...



Senden (Post) Benachrichtigung

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

Benachrichtigung erhalten (erhalten)

NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil)

Benachrichtigung entfernen

NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed

Methodenhandler für empfangene Benachrichtigung

func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

Annotiere entweder die Klasse oder die Zielmethode mit @objc

@objc private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

// Or

dynamic private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}
703

Swift 3.0 in Xcode 8

Swift 3.0 hat viele "stringly typisierte" APIs durch struct "Wrapper-Typen" ersetzt, wie dies bei NotificationCenter der Fall ist. Benachrichtigungen werden jetzt durch einen struct Notfication.Name und nicht durch String identifiziert. Siehe Migration auf Swift 3 .

Vorherige Verwendung:

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

Neue Swift 3.0-Nutzung:

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

Alle Systembenachrichtigungstypen sind jetzt als statische Konstanten in Notification.Name definiert. d.h. .UIDeviceBatteryLevelDidChange, .UIApplicationDidFinishLaunching, .UITextFieldTextDidChange usw.

Sie können Notification.Name mit Ihren eigenen benutzerdefinierten Benachrichtigungen erweitern, um mit den Systembenachrichtigungen konsistent zu bleiben:

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

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

Eine gute Möglichkeit, dies zu tun, ist die Verwendung der addObserver(forName:object:queue:using:) -Methode anstelle der addObserver(_:selector:name:object:) -Methode, die häufig aus Objective-C-Code verwendet wird. Der Vorteil der ersten Variante besteht darin, dass Sie das @objc-Attribut nicht für Ihre Methode verwenden müssen:

    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)

und Sie können sogar eine Schließung anstelle einer Methode verwenden, wenn Sie möchten:

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

Sie können den zurückgegebenen Wert verwenden, um die Benachrichtigung später zu beenden:

    NotificationCenter.default.removeObserver(observer)

Bei der Verwendung dieser Methode gab es einen weiteren Vorteil: Sie mussten keine Selector-Strings verwenden, die vom Compiler nicht statisch überprüft werden konnten. Sie waren daher sehr empfindlich, wenn die Methode umbenannt wurde enthalten später #selector Ausdrücke , die das Problem beheben.

37
Jon Colverson
  1. Deklarieren Sie einen Benachrichtigungsnamen

    extension Notification.Name {
        static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
    }
    
  2. Sie können Beobachter auf zwei Arten hinzufügen:

    Selector verwenden

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

    oder block verwenden

    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. Veröffentlichen Sie Ihre Benachrichtigung

    NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
    

von iOS 9 und OS X 10.11. Es ist nicht mehr für ein .__ erforderlich. NSNotificationCenter-Beobachter, der sich selbst abmeldet, wenn er .__ ist. freigegeben. Mehr Info

Für eine block-basierte Implementierung müssen Sie einen schwach-starken Tanz ausführen, wenn Sie self im Block verwenden möchten. Mehr Info

15

Daten mit NSNotificationCenter übergeben

Sie können Daten auch mit NotificationCentre in Swift 3.0 und NSNotificationCenter in Swift 2.0 übergeben.

Swift 2.0 Version

Informationen über userInfo übergeben, ein optionales Dictionary vom Typ [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

Die userInfo nimmt jetzt [AnyHashable: Any]? als Argument, das wir in Swift als Wörterbuchliteral zur Verfügung stellen

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

Quelle Daten mit NotificationCentre (Swift 3.0) und NSNotificationCenter (Swift 2.0) übergeben

7
Sahil

Wir sollten auch die Benachrichtigung entfernen.

Ex.

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

}
2
Pankaj Jangid

Ich kann einen der folgenden Schritte ausführen, um einen Selektor erfolgreich zu verwenden - ohne mit @objc etwas zu kommentieren:

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)    

Meine Xcrun-Version zeigt Swift 1.2, und dies funktioniert auf Xcode 6.4 und Xcode 7 Beta 2 (von denen ich dachte, dass sie Swift 2.0 verwenden würde):

$xcrun Swift --version

Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)
2
leanne

In Swift 2.2 - XCode 7.3 verwenden wir #selector für NSNotificationCenter

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

In Swift 5

Angenommen, Sie möchten Daten von ViewControllerB an ViewControllerA empfangen

ViewControllerA (Empfänger)

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 (Absender)

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

In Swift 3, Xcode 8.2: - Überprüfen des Batteriezustands

//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 Hinzufügen von Beobachtersyntax in Swift 4.0 für iOS 11  

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

Dies ist für den Typ der Benachrichtigungsnamen keyboardWillShow. Ein anderer Typ kann aus der verfügbaren Option ausgewählt werden 

der Selector ist vom Typ @objc func, der die Anzeige der Tastatur behandelt (dies ist Ihre Benutzerfunktion)

0
Ashim Dahal

Swift 5 & Xcode 10.2:

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