最近在做項目的時候俏橘,遇到了一個需求允华。我有三個 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ā),我是否可以通過訂閱方法處理來完成我想要的需求呢蔓同?我們在設置屬性時必然會走 set
方法饶辙。
嗯,這個好像是我們需要的方法斑粱,那就看看能否實現(xiàn)吧弃揽。
好像起作用了,但我們可以做進一步的優(yōu)化则北。我希望事件就給我返回個 Bool
,而且包含一開始的默認屬性矿微。
這樣就得到我想要的結果了??,但我可以讓它變得更好用點尚揣,把它封裝到 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
如果大家有更好的方法,歡迎分享討論惑艇。
最后:歡迎討論蒿辙、批評、指錯滨巴。