I am having problem understanding the rationale and purpose for asObservable method in RxSwift's Observable class.
/// A type-erased `ObservableType`.
///
/// It represents a push style sequence.
public class Observable<Element> : ObservableType {
/// Type of elements in sequence.
public typealias E = Element
public func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
abstractMethod()
}
public func asObservable() -> Observable<E> {
return self
}
}
What's the purpose of asObservable when it's returning self?
Surely if you can run this method, you already have access to the object. Also, what does the "type-erased ObservableType
" in the comment means?
I believe the answer is apparent if you look at the ObservableType
protocol and what objects conform to it (namely things like subjects, etc.).
The only guarantee is that the object will return an Observable
in response to a call to asObservable
. While conformance is trivial for an Observable
, it may be less so for subjects and other units. But this guarantee allows you to use all type that can provide an Observable
together in the same operator chain.
In essence this is similar to String
s conformance to CustomStringConvertible
.
You asked two questions:
1. What's the purpose of asObservable when it's returning self?
You almost don't need to ever use asObservable()
. The only time I think you'd need is when you're assigning casting a Subject/Relay to an Observable.
Suppose you have a variable that is a BehaviorRelay
. It can both, observe and be an observable.
ViewModel.swift
let deviceOrientation = BehaviorRelay<UIInterfaceOrientation>(value: UIApplication.shared.statusBarOrientation)
And then you have a variable that is not both but only an observable like below.
ViewController.swift
lazy var incorrect : Observable<UIInterfaceOrientation> = {
return self.viewModel.deviceOrientation // ERROR
}()
lazy var correct : Observable<UIInterfaceOrientation> = {
return self.viewModel.deviceOrientation.asObservable()
}()
Then you'd need to cast so you'd have the correct type.
The incorrect variable would give the following error:
Cannot convert value of type
BehaviorRelay<UIInterfaceOrientation>
to closure result typeObservable<UIInterfaceOrientation>
2. What does the "type-erased ObservableType" in the comment means?
I suspect Scott's comment is semi-correct. I mean for sure it's confusing. You can flatten the type of a BehvaiorRelay
, PublishSubject
to a Observable
and then assign one Observable to another. Otherwise still they all require the associatedType to be given ie no type erasure happening.
let x : AnyHashable = 10
let y : AnyHashable = "Alex"
if x == y { print("equal" } // compiles!
var i = PublishSubject<Int>().asObservable()
var s = PublishSubject<String>().asObservable()
if i == s { print("equal" } // does NOT compile. Gives following error:
Binary operator
==
cannot be applied to operands of typeObservable<Int>
andObservable<String>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With