最近在做項目的時候,遇到了一個需求。我有三個 View(View1, View2, View3),View1 和 View2 其中一個顯示,View3 就顯示。
稍微思考了一下,覺得訂閱 isHidden 屬性的改變,然后通過 CombineLatest 組合 Observable 來實現(xiàn)。
問題
而問題就來了。。。

isHidden 居然是個 UIBindingObserver<UIView, Bool>
嘗試使用 KVO
我在使用 OC 時,會使用 ReactiveCocoa 。而在 ReactiveCocoa 我經(jīng)常使用 KVO 去監(jiān)控屬性。或者在 RxSwift 也有類似的方法吧?

好像的確有類似的東西,那就到源碼中查看怎么使用吧。。。

從這些注釋,大概知道了使用方法,那就開干吧。。。

只打印了 next(Optional(false)), 并不能監(jiān)控到 isHidden 值的變化=。=
為什么呢?難道我使用方法不對?找找可參照的例子。
在 KVOObservableTests.swift 找到了一段測試代碼:

注意,這里的屬性都使用了 dynamic , 感覺好像抓到了些什么?先嘗試定義一個類試試看。

起作用了??,那把 dynamic 刪了呢?

又不好使了?? 為什么呢?
其實喵神在《Swift 開發(fā)必備 Tips》中就提過這個問題。

所以,只能另想辦法了??
使用 methodInvoked
還記得 UITextField 經(jīng)常使用的 text 屬性么?它又是怎么實現(xiàn)的呢?

查看源碼,發(fā)現(xiàn)它使用了 UIControl 的 value 方法。繼續(xù)往下看。。。

這里是通過監(jiān)控控件事件來實現(xiàn)的。。??那么 textField.rx.text.subscribe 同樣存在一個問題
textField.text = "test"
這樣的操作,也是沒法得到事件的。。
但可以從這個段代碼中得到給啟發(fā),我是否可以通過訂閱方法處理來完成我想要的需求呢?我們在設(shè)置屬性時必然會走 set 方法。

嗯,這個好像是我們需要的方法,那就看看能否實現(xiàn)吧。

好像起作用了,但我們可以做進(jìn)一步的優(yōu)化。我希望事件就給我返回個 Bool,而且包含一開始的默認(rèn)屬性。

這樣就得到我想要的結(jié)果了??,但我可以讓它變得更好用點,把它封裝到 rx 中作為一個 hidden 屬性好了
extension Reactive where Base: UIView {
var hidden: Observable<Bool> {
return self.methodInvoked(#selector(setter: self.base.isHidden))
.map { event -> Bool in
guard let isHidden = event.first as? Bool else {
fatalError()
}
return isHidden
}
.startWith(self.base.isHidden)
}
}

嗯,現(xiàn)在就可以愉快的訂閱 hidden 屬性了 (^-^)V
如果大家有更好的方法,歡迎分享討論。
最后:歡迎討論、批評、指錯。