Swiftで遊ぼう! - 715 - Notificationもう少し続けます。
昨日小さなNotificationデモを説明しましたが、スタンフォード大学のポール先生のNotification実装方法が違うんです。
ということで少しだけデモを拡張します。実はNotificationクラスのインスタンスを作ってaddObserverメソッドを使って実装する方法がまだあります。
AppDelegateクラスに次のNotification.Nameクラスのグローバル定数を作ります。
static let AnotherNotification = Notification.Name("AnotherApplicationDidEnterBackground")
そしてこの名前でNotificationクラスのインスタンスを作ります。どこでコードを書くか?applicationDidEnterBacground()メソッド内に加えます。
let notification = Notification( name: AppDelegate.AnotherNotification, object: nil, userInfo: ["key" : "Thisi is another notification message"])
この時重要なのがuserInfoのようです。[ String : AnyObject ]でkye-Valueのテクニックを使って色々と拡張できそうですが、今のところ私には、これを上手く利用する能力がありません(^_^;)。取りあえずメッセージを保持させました。
そして、このNotificationインスタンスをpostします。
この「post」メソッドには次の3つの種類がありました。
func post(Notification) //1. 別途に作られたNotificationを送信するメソッドです。 func post(name: NSNotification.Name, object: AnyObject?) //2. これは名前とオブジェクトからNotificationを作って // 送信するメソッドです。 func post(name: NSNotification.Name, object: AnyObject?, userInfo: [NSObject : AnyObject]? = [:]) //3. 上記と同様でNotificationを作って送信しますが、 // userInfoという情報も送れます。
当然、Notificationインスタンスを別途に作っているので、(1)のメソッドを使います。
ns.post(notification)
ここまでがAppDelegateクラスに加えたコードです。そしてこのNotificationを受け取るクラスがViewControllerなのでNotificationCenterにObserverとして登録します。
この登録するためのメソッド「addObserver」にもいくつか種類があります。
昨日のデモで使ったメソッドは次のselectorを使用するパターンで2つ用意されています。パラメータとしてString型の「name」を受け取るメソッドです。これは従来のStringy-typed型のシステムNotificationを扱う時に使います。
func addObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?)
そしてSwift 3βで用意されているのが次のメソッドです。
func addObserver(observer: AnyObject, selector: Selector, name: Name, object: AnyObject?)
Notification.Name型の「name」を受け取るメソッドなので、今のところは混在できます。
しかし、スタンフォード大学のポール先生は、iOS9開発講義の中で、もう一つのメソッドを使って説明しています。
func addObserver(forName: NSNotification.Name?, object: AnyObject?, queue: OperationQueue?, using: (Notification) -> Void)
このメソッドが一番OOP向きのメソッドでないかと思います。どう考えればいいのか良くわかりませんが、スレッドも考慮されています。Notificationから情報を受け取ることができ、コードをブロック(クロージャ)で処理することができます。そして上記の2つのメソッドがVoidを返すのと異なり、「NSObjectProtocol」型を返すんです。
ということでViewControllerに次の宣言を加えます。
var observer: NSObjectProtocol? = nil
オプショナル型のobserverを宣言して、viewDidLoad()メソッド内で実装させます。
override func viewDidLoad() { super.viewDidLoad() // カスタムNotificationをNotificationCenterに登録 // 昨日の記事と同じ NotificationCenter.default().addObserver( self, selector: #selector(someAction), name: AppDelegate.originalNotification, object: nil) // システムで用意されているNotificationは「String」型を引数として受け取れます。 // 昨日の記事と同じ NotificationCenter.default().addObserver( self, selector: #selector(anotherAction), name: "UIApplicationDidEnterBackgroundNotification", object: nil) // 今日付け加えたコード observer = NotificationCenter.default().addObserver( forName: AppDelegate.AnotherNotification, object: nil, queue: OperationQueue.main(), using: { notification in if let sample = notification.userInfo?["key"] as? String { print(sample) } }) }
当然deinitメソッドも少し変更になります。
deinit { NotificationCenter.default().removeObserver(self) if let acitiveObserver = observer { NotificationCenter.default().removeObserver(acitiveObserver) } }
これをランしてHomeに戻ると次のように表示されました。
This is original notification message.
Thisi is another original message
This is system notification message.
これで何となく基本的なNotificationの挙動が理解できました。
今日はこれだけ。