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

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

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


```swift
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`をインスタンス化したものを利用しているのかということです。
`notificationCenter` →`NotificationCenter.default`

```swift
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`などでもこの考え方は活きるかと思います。もしかしたらこっちの方が一般的かも。

```swift
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`型の変数を使えるようになりました。