rxswift 绑定(onNext:VS 订阅(onNext:

Posted

技术标签:

【中文标题】rxswift 绑定(onNext:VS 订阅(onNext:【英文标题】:rxswift bind(onNext: VS subscribe(onNext: 【发布时间】:2019-03-22 06:50:34 【问题描述】:

我有两个问题:

    'bind(onNext:' 和 'subscribe(onNext:' 有什么区别?
struct Info 
    var index: Int?
    var data: String?


let infoData: BehaviorRelay<Info> = BehaviorRelay<Info>(value: Info())
var osInfo: Observable<String>  return self.infoData.map( return $0.data ).distinctUntilChanged() 

osInfo.bind  (target) in
    print("bind!")
    .disposed(by: self.disposeBag)

osInfo.subscribe  (target) in
    print("subscribe!")
    
    .disposed(by: self.disposeBag)
    a 没有 asObservable(),但可执行性很好。 a和b有什么区别?
a. var osInfo: Observable<String>  return self.infoData.map( return $0.data ).distinctUntilChanged() 
b. var osInfo: Observable<String>  return self.infoData.asObservable().map( return $0.data ).distinctUntilChanged() 

【问题讨论】:

【参考方案1】:

'bind(onNext:' 和 'subscribe(onNext:' 有什么区别?

如果我们检查 bind(...) 的实现,我们会发现它什么也不做,只是在底层使用 subscribe(...) 并在 Debug 中崩溃并出现错误:

/**
Subscribes an element handler to an observable sequence. 

In case error occurs in debug mode, `fatalError` will be raised.
In case error occurs in release mode, `error` will be logged.

- parameter onNext: Action to invoke for each element in the observable sequence.
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
public func bind(onNext: @escaping (E) -> Void) -> Disposable 
    return subscribe(onNext: onNext, onError:  error in
        rxFatalErrorInDebug("Binding error: \(error)")
    )

通过使用bind(onNext),您可以表示该流不应该发出错误并且您只对项目事件感兴趣。

因此,当您对错误/完成/处置事件感兴趣时应使用subscribe(onNext:...),否则应使用bind(onNext...)。但由于它是RxCocoa 的一部分而不是RxSwift,所以我通常在任何地方都使用subscribe

a 没有 asObservable(),但可执行性很好。 a和b有什么区别?

map(...) 是在ObservableType 上声明的函数并返回新的Observable

让我们从ObservableType开始。ObservableType是只需要一种方法的协议:subscribe(...),这允许他创建func asObservable()的默认实现。 对您而言,这意味着您可以从任何符合ObservableType 的类型创建Observable

/// Represents a push style sequence.
public protocol ObservableType : ObservableConvertibleType 
    func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E

extension ObservableType 
    /// Default implementation of converting `ObservableType` to `Observable`.
    public func asObservable() -> Observable<E> 
        // temporary workaround
        //return Observable.create(subscribe: self.subscribe)
        return Observable.create  o in
            return self.subscribe(o)
        
    

因此,每次您调用 asObservable() underhood RxSwift 时,都会在您的流周围创建新的 Observable 包装器。

如果您检查BehaviourRelay 的来源,您会发现它也符合ObservableType。所以你可以随时从中创建Observable

public final class BehaviorRelay<Element>: ObservableType  ... 

现在让我们检查map 函数:

extension ObservableType 

    /**
     Projects each element of an observable sequence into a new form.

     - seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)

     - parameter transform: A transform function to apply to each source element.
     - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.

     */
    public func map<R>(_ transform: @escaping (E) throws -> R)
        -> Observable<R> 
        return self.asObservable().composeMap(transform)
    

正如预期的那样,map 只需在内部调用asObservable() 并在新的Observable 上进行操作。

如果我们“解包”map 调用,我们将得到:

var osInfoA: Observable<String> 
    return infoData
        .asObservable()
        .composeMap  $0.data 
        .distinctUntilChanged()

var osInfoB: Observable<String> 
    return infoData
        .asObservable()
        .asObservable()
        .composeMap  $0.data 
        .distinctUntilChanged()

当然它不会编译,因为composeMap 是内部函数,但你明白了主要思想。 在其他运算符之前调用 asObservable 是多余的(大多数运算符在 ObservableType 上定义)并且只会增加少量开销。

【讨论】:

以上是关于rxswift 绑定(onNext:VS 订阅(onNext:的主要内容,如果未能解决你的问题,请参考以下文章

调用 .onNext(newArray) 时 RXSwift collectionView 不更新

RxSwift 共享订阅执行顺序

为啥我的 onNext 没有触发我的 rx 订阅?

等待多个可观察请求完成使用 RXSwift

RxSwift 订阅者接收多个事件

完成块内的 RxSwift 订阅问题