Protocolを利用したNotificationCenter

More than 1 year has passed since last update.


はじめに

14日目は、(株)スマートテック・ベンチャーズの串田(@eKushida)が担当します。

Swift3バージョンアップに伴い、

NSNotificationCenterのクラス名が

NotificationCenterに変更になりましたね。

他にも下記のメソッドに変更が入っています。


変更点

機能
Swift2
Swift3

生成する
.defaultCenter()
.default

通知する
postNotificationName("listDidLoad")
post(name: NSNotification.Name("listDidLoad")

さて本題ですが、

今回は、NotificationCenterをプロトコルを利用して

実装したいと思います。


実装手順


1. プロトコルを定義する


1.1. 付属型でNotificationを定義する


Notifier.swift

protocol Notifier {

associatedtype Notification: RawRepresentable
}


1.2. 通知用のプロトコルにNotificationCenter用のラッパーメソッドを拡張する

RawValueがStringのものだけを対象とします。


Notifier.swift

extension Notifier where Notification.RawValue == String {

//RawValueをString型に変換する
fileprivate static func nameFor(notification: Notification) -> String {
return "\(notification.rawValue)"
}
// 登録用のラッパーメソッド
static func addObserver(observer: AnyObject,
selector: Selector,
notification: Notification) {
let name = nameFor(notification: notification)

NotificationCenter.default.addObserver(observer,
selector: selector,
name: NSNotification.Name(rawValue: name),
object: nil)
}

// 通知用のラッパーメソッド
static func postNotification(notification: Notification,
object: AnyObject? = nil,
userInfo: [String : Any]? = nil) {

let name = nameFor(notification: notification)

NotificationCenter.default.post(name: NSNotification.Name(rawValue: name),
object: object,
userInfo: userInfo)
}

// 削除用のラッパーメソッド
static func removeObserver(observer: AnyObject,
notification: Notification,
object: AnyObject? = nil) {

let name = nameFor(notification: notification)

NotificationCenter.default.removeObserver(observer,
name: NSNotification.Name(rawValue: name),
object: object)
}
}



2. イベントを定義する


2.1. イベントクラスにNotifierプロトコルを実装し、イベント名を定義する


Event.swift

final class Event: Notifier {

enum Notification: String {
case photoListDidLoad
case photoDetailDidLoad
}
}



3. 利用方法

ロードボタンを押下すると、通知を受信するサンプルです。

(同一画面内で登録→通知→通知受信→削除まで)


ViewController.swift


import UIKit

extension Selector {
static let photoListDidLoad = #selector(ViewController.photoListDidLoad)
}

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
add()
}

//登録
func add() {
Event.addObserver(observer: self,
selector: .photoListDidLoad,
notification: .photoListDidLoad)
}

//通知を受け取る
func photoListDidLoad(notification: Notification) {
print(#function)

Event.removeObserver(observer: self,
notification: .photoListDidLoad)
}

@IBAction func didLoadTap(_ sender: UIButton) {
post()
}

//通知
fileprivate func post() {
Event.postNotification(notification: .photoListDidLoad)
}
}



まとめ

参考サイトをベースにSwift3に置き換えてみました。

大変勉強になりました。

ソースコードは、Githubにアップしてあります。

よろしければ、ご一緒に御覧ください。

誤り等ございましたら、ご指摘頂けますと、幸いです。

スマートテック・ベンチャーズでは、未経験だけどiOSの開発をやりたい!という人を募集しています。

Advent Calendarのスマートテック・ベンチャーズページに会社およびWantedlyのURLをのせていますので、興味のある方は是非ご覧ください。

https://www.wantedly.com/companies/st-ventures/info

明日は、@soudapさんです。

お楽しみに!