NSObject-Rxの実装を紐解きます。
RxSwiftを利用していれば、おそらく利用したことのあるライブラリ、RxSwiftCommunity/NSObject-Rx
。
一応解説しておくと、NSObject
のサブクラスであれば、DisposeBag
を宣言する必要なく利用することができるという便利な代物です。
RxSwiftで開発をしているととても良く使うライブラリの一つではないでしょうか。
今回、ひょんなことからこのライブラリがどのようにしてdisposeBag
を実装しているのかを確認してみたくなって、びっくりしたので、まとめておきます。
Swiftの機能のみを利用した実装ではない。
今回話しているRxSwiftCommunity/NSObject-RX
は、Swiftの機能のみを利用した実装にはなっていません。
NSObject-Rx
の実体ファイルは下記ファイルなのですが、結構無茶苦茶やってますね。
大まかな流れは、
-
Reactive
Protocolのデフォルト拡張をBase: AnyClass
に指定(すべてのクラスでデフォルト拡張される) Objective-Cの
メンバ変数追加
ができるAssociated Object
というびっくり黒魔術を利用してDisposeBag
を宣言
(SwiftでObjective-Cの黒魔術ってどうなった?: https://qiita.com/fmtonakai/items/e9036dec4af2609b5715)初回アクセス時には生成、セット時には
setter
内部でセットされたdisposeBagをAssociated Object経由でプロパティかのように保持disposeBagの生成、アクセス処理は
objc_sync_enter
、objc_sync_exit
で強制同期。
結構すごい実装になってました。
ちなみになんですが、Associated Object
はピュアSwiftだと動作しないようなので、Ubuntuとかで開発する場合は、うまくいかない感じだと思われます。
読み解いてみて
Objective-C
由来の黒魔術がこんなところで生かされていたのが結構驚きでした。