備忘録として。何か良い手段があれば教えていただきたいです。
まとめ
.rx
によるアクセスのために必要な DelegateProxy の Method Swizzling のために Delegate method には @objc
メソッドが,Delegate method の @objc func
を呼ぶためにクラスには NSObject
の継承が必要で,
それらはObjective-Cランタイムを利用するため,(ランタイムを持たない) Linuxでは使用できない
やりたかったこと
あるクラスを RxSwift を import しない状態で,extension によってrxプロパティ経由では変更を通知できるようにしたかった。
具体的には,
時間計測を行う IntervalTimer.swift の milliseconds
プロパティが変化するタイミングで,通常は現在の値しか取れないが,.rx.milliseconds
経由では BehaviorRelay<Int>
として Observable に変更を通知できるようにしたい。また,その拡張を外側から実装したい。なお,通知方向は一方向とし,アクセス側からは変更されないものとする。
Non Rx class ---> Rx extension ---> Rx class recieved KVO
という意図から始まった。
class Timer {
fileprivate(set) var milliseconds: Int
}
extension Timer: ReactiveCompatible {}
extension Reactive where Base: Timer {
/// Reactive wrapper for `milliseconds` message.
var milliseconds: BehaviorRelay<Int> {
// ほげふが
}
}
let timer = Timer()
timer.milliseconds // -> Int
timer.rx.milliseconds // -> BehaviorRelay<Int>
試したこと
通常の RxCocoa の実装では, DelegateProxy を利用して Delegate method を外側から Reactive struct に適合するように extension を生やし,
ReactiveCompatible によって .rx
記法を利用できるようにした。
なぜ利用できなかったのか
The Swift Linux Port | Swift.org によると,
- Runtime Introspection: When a Swift class on Apple’s platforms is marked @objc or subclasses NSObject you can use the Objective-C runtime to enumerate available methods on an object or call methods using selectors. Such capabilities are absent because they depend on the Objective-C runtime.
@objc
や NSObject
はObjective-Cランタイムを利用するため,(ランタイムを持たない) Linuxでは使用できない
ということらしい。
どこで利用していたのか
RxCocoa では Delegate method の解決のために NSObject+Rx.swift にて sentMessage()
および methodInvoked()
が利用できるものの,その引数は Selector
でした。
Selector
は @objc
method でしか利用できませんでした (最終的に Method Swizzling に利用され,NSObject
が必要)。
.rx
によるアクセスのために必要な DelegateProxy の Method Swizzling のために Delegate method には @objc
メソッドが,Delegate method の @objc func
を呼ぶためにクラスには NSObject
の継承が必要で,
それらは Objective-C ランタイムを利用するため,(ランタイムを持たない) Linuxでは使用できない
ということでした。
結局どうしたのか
どうにかできれば登壇材料でしたが,僕の力ではできなかったので素直に rx property を元のクラスに生やしました。
何か良い方法があれば教えていただきたいです......
最後に,頑張って追加した DelegateProxy と,それを泣く泣く消したコミットを添えておきます。お酒のおつまみにでも利用してください。