RxSwift 调度者(三)

RxSwift 调度者(三)

补充 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)") })
  • 一般来说 publishconnect 连用
  • 继承链 publish -> multicast -> ConnectableObservableAdapter: ConnectableObservable -> ConnectableObservable: Observable
  • 所以 publish 只有 subscribe方法没有 on 方法
  • 底层有一个 lazySubject 只初始化一次观察者,当有多次的subscribe时,只执行第一次的 subscribe
  • connect 执行Connection: ObserverType 自己实现on方法

UI 事件一定在主线程

DispatchQueue.global().async {
            
    self.button.rx.tap
        .subscribe(onNext: { _ in
          print("\(Thread.current)")
        })
}
  • self.button.rx.tap 是封装了ControlEvent
  • ControlEvent进行subscribe的时候 event 默认执行了subscribeOn进入主线程

PublishSubject

  • PublishSubject 即是观察者也是订阅者
  • 只接受订阅后发送的数据
  • 创建 subject -> 收集观察者回调 -> 拿到

BehaviorSubject

  • BehaviorSubjectPublishSubject类似,但是会保存订阅前的一个数据

BehaviorRelay 可以直接设置和拿到值

let br = BehaviorRelay<Int>(value: 100)
        
br.accept(1000)
    
br.value

总结:一般我们在页面传值的时候用 subject 比较多,序列的传递

Dispose

  • DisposeBag 底层有一个数组,保存了当前所有 bag 调用 dispose 或者重新初始化的话的时候回销毁
  • 或者拿到创建的序列返回的disposeable 进行 dispose

KVO

  • Swift KVO 底层也是对 OC 的 KVO 进行了封装
  • RAC 同理
  • KVO 底层原理通过 runtime 创建当前监听类的子类实现监听属性的 get、set 方法,最终实现 change 的改变

RxSwift 内存管理

  • pod 里导入
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
  • 打印计数RxSwift.Resources.total
override func viewWillAppear(_ animated: Bool) {
   super.viewWillAppear(animated)
       
    print("计数viewWillAppear:\(RxSwift.Resources.total)")
}
        
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("计数viewWillDisappear:\(RxSwift.Resources.total)")

}
  • subscribe注意循环引用
  • VC.bag 时注意循环
  • unowned 无主引用,确保访问时不会被释放,因为设置后会一直引用对象,即使对象被释放了也会保持一个无效的引用,如果调用这个引用对象(无效引用)的方法就会崩溃
  • weak 弱引用处理,作用域结束后清除弱引用对象
  • 通过实现

中介者模式

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 {
            // 容错处理~ 可以通过 Runtime 来创建没实现的 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 关键字保证不被循环引用
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容