読者です 読者をやめる 読者になる 読者になる

SwiftからNSNotificationCenterを利用してみるメモ

今回は完全に自分用メモです。

背景もへったくれもなく、人に読んで頂くための記事でもなく、本当にふと思いついて試したことを忘れないうちにメモっておくために走り書いた感じです。

このへんを参考に、Swift から NSNotificationCenter を使って「通知」の仕組みを作ろうというお話。

Xcode 6 beta 3 で動作確認しています。

ちなみにSwift は言語仕様の破壊的な改訂がけっこうひんぱんに行われており、以下のコードは Xcode 6 beta 2 以前の処理系ではコンパイルエラーになります。

(※ちなみに、はてなブログは7月13日時点で Swiftシンタックスハイライトに対応していないため、暫定的にActionScriptモードで表示しています)

// Xcode 6 beta 3 で動きます
import Foundation


// 監視をする人(通知を受ける人)
// -------------------------
class ConcreteObserver {
    // オブザーバオブジェクトをプールしておくところ
    var observers = [AnyObject]()

    // 監視対象のオブジェクト
    var subject:ConcreteSubject

    // イニシャライザ
    init() {
        subject = ConcreteSubject()
        
        // Subjectさんの変更を通知してもらえるよう、通知センターに登録します
        observers += NSNotificationCenter.defaultCenter()
            .addObserverForName(subject.PropertyChangedEvent,
                object: nil,
                queue: NSOperationQueue.mainQueue()) { notification in
                    var sender = notification.object as ConcreteSubject
                    var eventArgs = notification.userInfo
                    
                    println("通知速報")
                    println("\tプロパティの値が \(sender.number) に変更されました")
                    
                    println("追加情報")
                    for (key, value) in eventArgs {
                        println("\t\(key):\(value)")
                    }
                    
                    println()
                };
    }
    
    // 監視を開始します
    func execute() {
        subject.execute()
    }
    
    // デイニシャライザ
    deinit {
        // 死に際にオブザーバの登録を解除します
        for observer in observers {
            NSNotificationCenter.defaultCenter()
                .removeObserver(observer);
        }
        observers.removeAll(keepCapacity: false);
    }
}

// 監視をされる人(通知を送る人)
// -------------------------
class ConcreteSubject {
    // イベントを識別するための文字列です(てきとうにUUIDにしてみました)
    let PropertyChangedEvent = NSUUID.UUID().UUIDString
    
    // 通知回数を数えるための変数です
    var notifyCounter = 0

    // プロパティです
    var number: UInt32 = 0 {
    didSet {
        // Dictionaryにまとめた情報を通知先に引き渡すことができます
        var eventArgs = ["通知回数": ++notifyCounter]
        
        // 通知を行います
        NSNotificationCenter.defaultCenter()
            .postNotificationName(PropertyChangedEvent,
                object: self,
                userInfo: eventArgs)
    }
    }
    
    // プロパティに適当な数字を20回セットします(やりすぎ)
    func execute() {
        for _ in 0..<20 {
            number = arc4random_uniform(50)
        }
    }
}

// 監視を実行
// ---------
var observer = ConcreteObserver()
observer.execute();

あ、ちなみに Swift にはプロパティ監視というイケてる機構がついています。

今回はプロパティの変更を捕捉した後、NSNotificationCenter を使って拡散しています。

実行結果

あんまし載せる意味は無いと思いますがいちおう念のため……

通知速報
	プロパティの値が 43 に変更されました
追加情報
	通知回数:1

通知速報
	プロパティの値が 29 に変更されました
追加情報
	通知回数:2

通知速報
	プロパティの値が 17 に変更されました
追加情報
	通知回数:3

通知速報
	プロパティの値が 36 に変更されました
追加情報
	通知回数:4

通知速報
	プロパティの値が 20 に変更されました
追加情報
	通知回数:5

通知速報
	プロパティの値が 30 に変更されました
追加情報
	通知回数:6

通知速報
	プロパティの値が 23 に変更されました
追加情報
	通知回数:7

通知速報
	プロパティの値が 48 に変更されました
追加情報
	通知回数:8

通知速報
	プロパティの値が 18 に変更されました
追加情報
	通知回数:9

通知速報
	プロパティの値が 31 に変更されました
追加情報
	通知回数:10

通知速報
	プロパティの値が 39 に変更されました
追加情報
	通知回数:11

通知速報
	プロパティの値が 1 に変更されました
追加情報
	通知回数:12

通知速報
	プロパティの値が 42 に変更されました
追加情報
	通知回数:13

通知速報
	プロパティの値が 32 に変更されました
追加情報
	通知回数:14

通知速報
	プロパティの値が 15 に変更されました
追加情報
	通知回数:15

通知速報
	プロパティの値が 30 に変更されました
追加情報
	通知回数:16

通知速報
	プロパティの値が 34 に変更されました
追加情報
	通知回数:17

通知速報
	プロパティの値が 48 に変更されました
追加情報
	通知回数:18

通知速報
	プロパティの値が 38 に変更されました
追加情報
	通知回数:19

通知速報
	プロパティの値が 8 に変更されました
追加情報
	通知回数:20

Program ended with exit code: 0

Copyright (c) 2012 @tercel_s, @iTercel, @pi_cro_s.