環境
Swift 2.3, Xcode 8.2
ふつうにNSNotificationCenterを使うと
こんなかんじになる。
// 通知
NSNotificationCenter.defaultCenter().postNotificationName("NotifName", object: nil)
// 購読
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(MyViewController.onRecievedNotif),
name: "NotifName",
object: nil
)
// 購読解除
NSNotificationCenter.defaultCenter().removeObserver(self)
// 通知を受けたときの処理
func onRecievedNotif() {
// do something
}
不満
- 購読解除を忘れそう
- コードが長い
- notificationNameのタイポがこわい
RxSwiftを使ってシンプルに書けるようにした
private let bag = DisposeBag()
// 通知
NSNotifConstants.webViewClosed.post()
// 購読 & 通知を受けたときの処理 & 自身が破棄されたときに購読解除
NSNotifConstants.webViewClosed.asObservable()
.subscribeNext { [unowned self] notif in
// do something
}
.addDisposableTo(self.bag)
実装
RxCocoa による NSNotificationCenter
の拡張メソッドrx_notification
を使用する。
NSNotifConstants.swift
import Foundation
import RxSwift
// NSNotificationCenterに使う
enum NSNotifConstants {
// メインのタブを変更した
case mainTab
// アプリがバックグラウンドからフォアグラウンドに復帰した
case appDidBecomeActive
// お知らせ一覧を取得した
case latestNotificationAtUpdated
// お知らせ一覧を確認した
case notificationsChecked
// 自分のプロフィールが更新された
case myProfileUpdated
// WebViewが閉じた
case webViewClosed
var name: String {
// 他のライブラリ等とnotificationの名前がかぶるのを防ぐためにprefixをつける
return "myapp" + String(self.hashValue)
}
// 通知を送る
func post(object: AnyObject? = nil, userInfo: [NSObject: AnyObject]? = nil) {
NSNotificationCenter.defaultCenter().postNotificationName(
self.name,
object: object,
userInfo: userInfo
)
}
// 通知を購読する
func asObservable() -> Observable<NSNotification> {
return NSNotificationCenter.defaultCenter()
.rx_notification(self.name)
.observeOn(MainScheduler.instance)
}
}
オブジェクトを送る場合
ときには通知と一緒にobject
を送りたい。
あまり綺麗ではないかもしれないが、こう書くことにした
// 通知
NSNotifConstants.myProfileUpdated.post(
NSNotificationData.MyProfileUpdated(
oldProfileData: oldData,
newProfileData: newModel.toData()
)
)
// プロフィールの変更を監視
NSNotifConstants.myProfileUpdated.asObservable()
.map { $0.object as! NSNotificationData.MyProfileUpdated }
.subscribeNext( [unowned self] profiles in
// do something
)
.addDisposableTo(self.bag)
実装
NSNotifData
// NSNotificationCenterに使う
// objectに指定するためにNSObjectを継承する
final class NSNotifData: NSObject {
final class MyProfileUpdated {
// 自分のプロフィールが更新された
let oldProfileData: MyProfileData?
let newProfileData: MyProfileData
init(oldProfileData: MyProfileData?, newProfileData: MyProfileData) {
self.oldProfileData = oldProfileData
self.newProfileData = newProfileData
}
}
}
さいごに
もっといい感じの実装があれば教えてください:)