LoginSignup
0
2

More than 3 years have passed since last update.

NotificationCenterでイベント処理を行おうとしたらうまくいかなかった話

Posted at

はじめに

NotificationCenterを使ってクラス間で通知処理を行おうとしたらうまくいかなかったのでそのメモを残します。コピペで動くようにしてあるので、Playgroundなどで貼り付けて確認できます。

うまくいかない場合

先にうまくいかない場合を紹介。ざっくり説明すると、Senderクラスはインスタンス化された時、testという通知キーワードをpostします。
Receiverクラスはインスタンス化された時、testという通知キーワードを受け取れるようにし、受け取ったらtest()を実行します。

import Foundation
class Sender {
    let notificationCenter = NotificationCenter()
    init() {
        notificationCenter.post(name: NSNotification.Name(rawValue: "test"),
                                        object: nil)
    }
}

class Receiver {
    let notificationCenter = NotificationCenter()
    init() {
        notificationCenter.addObserver(forName: .init(rawValue: "test"),
                                               object: nil,
                                               queue: nil,
                                               using: { [unowned self] notification in
                                                test()
                                               })
        }
    func test() {
        print("通知")
    }
}

let receiver = Receiver()
let sender = Sender()

うまくいく場合

うまくいく場合を紹介します。うまくいかなかった場合との違いはNotificationCenterをインスタンス化したものを利用しているのかということです。
notificationCenterNotificationCenter.default

import Foundation
class Sender {
    init() {
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "test"),
                                        object: nil)
    }
}

class Receiver {
    init() {
        NotificationCenter.default.addObserver(forName: .init(rawValue: "test"),
                                               object: nil,
                                               queue: nil,
                                               using: { [unowned self] notification in
                                                test()
                                               })
        }
    func test() {
        print("通知")
    }
}

let receiver = Receiver()
let sender = Sender()

原因

クラスでそれぞれNotificationCenterをインスタンス化して使っているのが原因でした。クラス間をまたいで使っていないのでできないことは当たり前といえば当たり前ですが。

おまけ

それでもインスタンス化したものを使いたい!という場合の対処法について記述します。レアケースかもしれませんが、AVAudioPlayerなどでもこの考え方は活きるかと思います。もしかしたらこっちの方が一般的かも。

import Foundation
class Sender {
    let notificationCenter = NotificationCenter()
    func send() {
        notificationCenter.post(name: NSNotification.Name(rawValue: "test"),
                                        object: nil)
    }
}

class Receiver {
    let notificationCenter: NotificationCenter
    init(initNC : NotificationCenter) {
        self.notificationCenter = initNC
        notificationCenter.addObserver(forName: .init(rawValue: "test"),
                                               object: nil,
                                               queue: nil,
                                               using: { [unowned self] notification in
                                                test()
                                               })
        }
    func test() {
        print("通知")
    }
}

let sender = Sender()
let receiver = Receiver(initNC: sender.notificationCenter)
sender.send()//通知

先ほどのうまくいかなかった場合のソースコードの一部を以下のように変更しました。

  • Senderクラスの通知を送る処理をinit()ではなくsend()で送るようにした。
  • ReceiverクラスにNotificationCenter型の変数を定義した。

このようにすることでクラス間で共通のNotificationCenter型の変数を使えるようになりました。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2