美文网首页Rx
RxSwift源码分析(6)——bind

RxSwift源码分析(6)——bind

作者: 无悔zero | 来源:发表于2020-10-04 15:29 被阅读0次

    平常使用RxSwift时经常用到bind函数,意思是绑定,把监听和响应绑定在一起。它使我们的代码变得更加简洁,非常好用,比如:

    //tf序列发送响应时,会作用在label上
    //相当于监听textField.text变化,然后响应label.text = textField.text
    textField.rx.text.bind(to: label.rx.text)
    
    1. 首先把这句代码拆分为三部分:textField.rx.textlabel.rx.text.bind(to: )
      先来看textField.rx.text,只是一个普通序列:
    extension Reactive where Base: UITextField {
        public var text: ControlProperty<String?> {
            return value
        }
        ...
    }
    

    再来看label.rx.text,是一个Binder,也是一个序列:

    extension Reactive where Base: UILabel {
        public var text: Binder<String?> {
            ...
        }
        ...
    }
    
    public struct Binder<Value>: ObserverType {
        ...
    }
    

    最后把上面两个序列绑定在一起的就是.bind(to: ).bind(to: )函数找出来有很多个,我们看对应类型的就行:

    extension ObservableType {
        @available(*, deprecated, renamed: "bind(to:)")//原来改名了,差点没找到
        public func bindTo<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
            return self.subscribe(observer)
        }
    }
    
    1. .bind(to: )函数内部其实自己进行了subscribe,根据RxSwift核心逻辑,将会调用observeron函数,observer也就是Binder
    public struct Binder<Value>: ObserverType {
        ...
        public func on(_ event: Event<Value>) {
            self._binding(event)
        }
        ...
    }
    
    1. self._binding()Binder初始化时保存的私有函数:
    public struct Binder<Value>: ObserverType {
        public typealias Element = Value
        
        private let _binding: (Event<Value>) -> Void
    
        public init<Target: AnyObject>(_ target: Target, scheduler: ImmediateSchedulerType = MainScheduler(), binding: @escaping (Target, Value) -> Void) {
            weak var weakTarget = target
    
            self._binding = { event in
                switch event {
                case .next(let element):
                    _ = scheduler.schedule(element) { element in
                        if let target = weakTarget {
                            binding(target, element)
                        }
                        return Disposables.create()
                    }
                case .error(let error):
                    bindingError(error)
                case .completed:
                    break
                }
            }
        }
        ...
    }
    

    我们还可以发现后面的调用会在主线程执行:

    1. 最终在主线程调用binding(target, element),这是Binder初始化时传过来的闭包:
    extension Reactive where Base: UILabel {
        /// Bindable sink for `text` property.
        public var text: Binder<String?> {
            return Binder(self.base) { label, text in
                label.text = text
            }
        }
        ...
    }
    
    1. 然后拿到textField.rx.text传递过来的text值,调用label.text = text,这样就完成了绑定。

    相关文章

      网友评论

        本文标题:RxSwift源码分析(6)——bind

        本文链接:https://www.haomeiwen.com/subject/pfywuktx.html