iOS
NSNotificationCenter
Swift
RxSwift

RxSwiftとenumでNSNotificationCenterを使いやすくした

More than 1 year has passed since last update.


環境

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
}
}

}



さいごに

もっといい感じの実装があれば教えてください:)