Swift3のNotificationCenterを今までと近い形で使ってみる

(追記) 正しい使い方は @mono0926 さんがこちらにて書いていますのでそちらへどうぞ :runner: 

 - [Swift 3 以降の NotificationCenter の正しい使い方](http://qiita.com/mono0926/items/754c5d2dbe431542c75e)

回れ右。
<br />

**※以下の内容は一応アーカイブとして残しておきますが、良き使い方ではないのでご了承くださいませ。**
<br />
<br />

-----

## Swift3.0で変わったNSNotificationCenter
Swift2からSwift3に変わって、Foundation系にも手が加えられ、 `NSNotificationCenter` 周りにも変更がありました。

Swift2.2とSwift3.0でaddObserveする場合の同じ処理を見比べてみます。

```swift:Swift2
class Hoge {
    @objc func doSomething(notification: Notification) {
        // ...
    }
}

NSNotificationCenter.defaultCenter().addObserver(
    self, 
    selector: #selector(hoge.doSomething(_:)), 
    name: "NotificationKey", 
    object: nil
)

```

```swift:Swift3
class Hoge {
    @objc func doSomething(_ notification: Notification) {
        // ...
    }
}

let hoge = Hoge()
NotificationCenter.default.addObserver(
    hoge, 
    selector: #selector(hoge.doSomething(_:)), 
    name: NSNotification.Name("NotificationKey"),  //おや...?
    object: nil
)

```

ここで、 **NSNotification.Name** という見慣れないものがでてきました。
(ちなみに *Notification.Name* ものもあって、辿ると **NSNotification.Name** のエイリアスになっているのでほぼ同義です。どちらで書いても間違いではなさそう。)

どうやらSwift3からは通知を発行するための`name`は`String`ではなくてこの`NSNotification.Name`を使えとなったようです。
しかし、これ毎回

```swift
NSNotification.Name("SomeNotificationKey")
```

ってやるの **しんどい** ですよね。
なので、今までどおりの形に近い感じで使えるようにしてみます。

----

## 魔法をかける
できれば今までどおり `name: "NotificationKey"` と書きたいので、 **NSNotification.Name** に魔法をかけます。
ここで、 **ExpressibleByStringLiteral** というprotocolの出番となります。
ちなみに、この **ExpressibleByStringLiteral** は、Swift2では *StringLiteralConvertible* という名前でした。

```swift:ExpressibleByStringLiteralをNotification.Nameに適応させる
extension NSNotification.Name: ExpressibleByStringLiteral {
    public init(unicodeScalarLiteral value: String) {
        self.init(rawValue: value)
    }
    
    public init(extendedGraphemeClusterLiteral value: String) {
        self.init(rawValue: value)
    }
    
    public init(stringLiteral value: String) {
        self.init(rawValue: value)
    }
}
```

こうすることで、

```swift
// good!
NotificationCenter.default.addObserver(
    hoge, 
    selector: #selector(hoge.doSomething(_:)), 
    name: "NotificationKey", 
    object: nil
)
```

このように、文字リテラル(`""`)を使って今までどおりの書き方ができるようになります。

...え、これが **変数の場合はどうするの？** ってなりますよね。
その場合は、変数を定義する型を **Notification.Name** にします。

```swift

class Hoge {
    // 左辺側で型を指定してあげることで、右辺はStringではなくて、Notification.Nameと推論される
    static let NotificationKey: NSNotification.Name = "NotificationKey"

    // NG : 今までどおりの宣言だと、Stringと推論される
    // static let NotificationKey = "NotificationKey"

    @objc func doSomething(_ notification: Notification) {
        // ...
    }
}

// good!
NotificationCenter.default.addObserver(
    hoge, 
    selector: #selector(hoge.doSomething(_:)), 
    name: Hoge.NotificationKey,  // 今までどおりいける！
    object: nil
)
```

## まとめ
Swift3になって **NSNotification.Name** とか出てきてちょっと怯んだのですが、少し工夫してあげると扱いやすくなるかもしれません。 **ExpressibleByStringLiteral** ありがとう。

## おまけ
そこそこ利用頻度の高い、`UIApplicationDidBecomeActiveNotification` といったUIApplication周りのNotificationのkeyに関しては、

```swift
// swift2まではこれ
UIApplicationDidBecomeActiveNotification
// swift3からはこれ
NSNotification.Name.UIApplicationDidBecomeActive
```

のように変わったので気をつけましょう。もしかしたら自動マイグレーションなり補完が効くかもしれませんが。。。
(最初どこに行ってしまったのか気づけなかった...)



*(※注 Xcode8 beta6 時点のSwift3.0を基に書いています。*