RxSwift 調(diào)度者(三)
補(bǔ)充 publish
let ob = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
let ob2 = ob.publish()
ob2.subscribe(onNext: { print("第一次:\($0)") })
ob2.connect()
ob2.subscribe(onNext: { print("第二次:\($0)") })
- 一般來說
publish 和 connect 連用
- 繼承鏈
publish -> multicast -> ConnectableObservableAdapter: ConnectableObservable -> ConnectableObservable: Observable
- 所以
publish 只有 subscribe方法沒有 on 方法
- 底層有一個(gè)
lazySubject 只初始化一次觀察者,當(dāng)有多次的subscribe時(shí),只執(zhí)行第一次的 subscribe
-
connect 執(zhí)行Connection: ObserverType 自己實(shí)現(xiàn)on方法
UI 事件一定在主線程
DispatchQueue.global().async {
self.button.rx.tap
.subscribe(onNext: { _ in
print("\(Thread.current)")
})
}
-
self.button.rx.tap 是封裝了ControlEvent
- 當(dāng)
ControlEvent進(jìn)行subscribe的時(shí)候 event 默認(rèn)執(zhí)行了subscribeOn進(jìn)入主線程
PublishSubject
-
PublishSubject 即是觀察者也是訂閱者
- 只接受訂閱后發(fā)送的數(shù)據(jù)
- 創(chuàng)建 subject -> 收集觀察者回調(diào) -> 拿到
BehaviorSubject
-
BehaviorSubject 和 PublishSubject類似,但是會(huì)保存訂閱前的一個(gè)數(shù)據(jù)
BehaviorRelay 可以直接設(shè)置和拿到值
let br = BehaviorRelay<Int>(value: 100)
br.accept(1000)
br.value
總結(jié):一般我們?cè)陧撁鎮(zhèn)髦档臅r(shí)候用 subject 比較多,序列的傳遞
Dispose
-
DisposeBag 底層有一個(gè)數(shù)組,保存了當(dāng)前所有 bag 調(diào)用 dispose 或者重新初始化的話的時(shí)候回銷毀
- 或者拿到創(chuàng)建的序列返回的
disposeable 進(jìn)行 dispose
KVO
- Swift KVO 底層也是對(duì) OC 的 KVO 進(jìn)行了封裝
- RAC 同理
- KVO 底層原理通過 runtime 創(chuàng)建當(dāng)前監(jiān)聽類的子類實(shí)現(xiàn)監(jiān)聽屬性的 get、set 方法,最終實(shí)現(xiàn) change 的改變
RxSwift 內(nèi)存管理
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'RxSwift'
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['-D', 'TRACE_RESOURCES']
end
end
end
end
end
- 打印計(jì)數(shù)
RxSwift.Resources.total
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("計(jì)數(shù)viewWillAppear:\(RxSwift.Resources.total)")
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
print("計(jì)數(shù)viewWillDisappear:\(RxSwift.Resources.total)")
}
- 當(dāng)
subscribe注意循環(huán)引用
-
VC.bag 時(shí)注意循環(huán)
- unowned 無主引用,確保訪問時(shí)不會(huì)被釋放,因?yàn)樵O(shè)置后會(huì)一直引用對(duì)象,即使對(duì)象被釋放了也會(huì)保持一個(gè)無效的引用,如果調(diào)用這個(gè)引用對(duì)象(無效引用)的方法就會(huì)崩潰
- weak 弱引用處理,作用域結(jié)束后清除弱引用對(duì)象
- 通過實(shí)現(xiàn)
中介者模式
class XCTimer: NSObject {
weak var target: NSObjectProtocol?
var sel: Selector?
var xcTimer: Timer? = nil
override init() {
super.init()
}
func xc_scheuledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any? = nil, repeats: Bool) {
self.xcTimer = Timer.init(timeInterval: ti, target: aTarget, selector: aSelector, userInfo: userInfo, repeats: repeats)
RunLoop.current.add(self.xcTimer!, forMode: .common)
self.target = aTarget as? NSObjectProtocol
self.sel = aSelector
guard self.target?.responds(to: self.sel) == true else {
return
}
let method = class_getInstanceMethod(self.classForCoder, #selector(timerAction))
class_replaceMethod(self.classForCoder, self.sel!, method_getImplementation(method!), method_getTypeEncoding(method!))
}
@objc
fileprivate func timerAction() {
if self.target != nil {
self.target!.perform(self.sel)
} else {
self.xcTimer?.invalidate()
self.xcTimer = nil
}
}
override func forwardingTarget(for aSelector: Selector!) -> Any? {
if self.target?.responds(to: self.sel) == true {
return self.target
}
else {
// 容錯(cuò)處理~ 可以通過 Runtime 來創(chuàng)建沒實(shí)現(xiàn)的 Selector
// class_addMethod(self.classForCoder, aSelector, imp_, <#T##types: UnsafePointer<Int8>?##UnsafePointer<Int8>?#>)
return super.forwardingTarget(for: aSelector)
}
}
}
let time = XCTimer()
time.xc_scheuledTimer(timeInterval: 1, target: self, selector: #selector(time), repeats: true)
func time() {
}
- 所有的邏輯在中介層處理,使用
weak 關(guān)鍵字保證不被循環(huán)引用