web-dev-qa-db-ja.com

SwiftでのNSNotificationCenter addObserver

Swiftのオブザーバをデフォルトの通知センターにどのように追加しますか?バッテリー残量が変化したときに通知を送信するこのコード行を移植しようとしています。

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

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:

NotificationCenter.default.addObserver(
    self,
    selector: #selector(self.batteryLevelChanged),
    name: UIDevice.batteryLevelDidChangeNotification,
    object: nil)

オブザーバがObjective-Cオブジェクトから継承しない場合は、セレクタとして使用するために、メソッドの前に@objcを付ける必要があります。

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

参照:NSNotificationCenterクラスリファレンスObjective-C APIとの対話

414
Connor

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)

受信した通知のFunction-Methodハンドラ:

@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

受信した通知のメソッドハンドラ

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

Xcode 8のSwift 3.0

NotificationCenterの場合と同様に、Swift 3.0は多くの "文字列型"のAPIをstruct "ラッパー型"に置き換えました。通知はStringではなくstruct Notfication.Nameによって識別されるようになりました。 Swift 3への移行ガイド を参照してください。

前の 用法:

// 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)
41
Jeffrey Fulton

これを行うための良い方法は、Objective-Cコードからよく使用される addObserver(forName:object:queue:using:) メソッドではなく、 addObserver(_:selector:name:object:) メソッドを使用することです。最初のバリエーションの利点は、メソッドに@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)

このメソッドを使用することにはもう1つの利点がありました。これは、コンパイラによって静的にチェックできないセレクタ文字列を使用する必要がないため、メソッドの名前を変更しても壊れにくいためです。後でその問題を修正する #selector を含めてください。

40
Jon Colverson
  1. 通知名を宣言する

    extension Notification.Name {
        static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
    }
    
  2. オブザーバを追加する方法は2つあります。

    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"]
    }
    
  3. あなたの通知を投稿

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

iOS 9およびOS X 10.11から。 NSNotificationCenterオブザーバは、割り当て解除時に登録解除する必要がなくなりました。 詳細情報

blockベースの実装では、ブロック内でselfを使用したい場合は、弱い - 強いダンスをする必要があります。 詳細情報

17

NSNotificationCenterを使用してデータを渡す

Swift 3.0ではNotificationCentreを、Swift 2.0ではNSNotificationCenterを使用してデータを渡すこともできます。

Swift 2.0バージョン

[NSObject:AnyObject]型のオプションのディクショナリであるuserInfoを使用して情報を渡しますか?

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)を使用してデータを渡す

8
Sahil

通知も削除する必要があります。

例.

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

}
2
Pankaj Jangid

次のいずれかを実行して、セレクタ - @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)    

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

Swift 2.2 - XCode 7.3では、NSNotificationCenter#selectorを使用しています

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

NSNotificationCenterSwift 4.0iOS 11にオブザーバ構文を追加

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

これは、keyboardWillShow通知名タイプ用です。利用可能なオプションから他のタイプを選択できます

selectorは、キーボードがどのように表示されるかを処理する@objc func型です(これはあなたのユーザー関数です)。

1
Ashim Dahal

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

}
1
swiftBoy

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

Swift 5&Xcode 10.2:

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