LoginSignup
9
8

More than 5 years have passed since last update.

Protocolを利用したNotificationCenter

Last updated at Posted at 2016-12-13

はじめに

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さんです。
お楽しみに!

9
8
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
9
8