RxSwift教程(三)

Variables represent some observable state.Variable without containing value can’t exist because initializer requires initial value.Variable wraps a subject.More specifically it is a BehaviorSubject.Unlike BahaviorSubject,it only exposes value interface,so variable can never terminate with error.
It will also broadcast its current value immediately on subscription.After variable is deallocated,it will commplete the observable sequence returned from .asObservable().
let variable = Variable(0)
print(“Before first subscription —-“)

_ = variable.asObservable()
.subscribe(onNext: { n in
print(“First (n)”)
}, onCompleted: {
print(“Completed 1”)
})
print(“Before send 1”)
variable.value = 1
print(“Before second subscription —–”)
_ = variable.asObservable()
.subscribe(onNext: { n in
print(“second (n)”)
}, onCompleted: {
print(“Completed 2”)
})
print(“Before send 2”)
variable.value = 2
print(“End ——”)
KVO(KVO is an Objective-C mechanism.That means that it wasn’t built with type safety in mind.This project tries to solve some of the problems.
These are two built in ways this library supports KVO.
//KVO
extension Reactive where Base: NSObject {

public func observe(type: E.type, _ keyPath: String, options: KeyValueObservingOptions, retainSelf: Bool = true) -> Observable

if !DISABLE_SWIZZLING

//KVO
extension Reactive where Base: NSObject {
public func observeWeakly(type: E.type, _ keyPath:String, options: KeyValueObservingOptions) -> Observable

endif

Example how to observe frame of UIView.
WARNING:UIKIT isn’t kvo compliant,but this will work.
view
.rx.observe(CGRect.self,”frame”)
.subscribe(onNext: { frame in
….
})
or
view
.rx.observeWeakly(CGRect.self,”frame”)
.subscribe(onNext: { frame in

})
rx.observe is more performant because it’s just a simple wrapper around KVO mechanism,but it has more limited usage scenarios.
.it can be used to observe paths starting from self or from ancestors in ownership graph(retainSelf = false)
.it can be used to observe paths starting from descendants in ownership graph(retainSelf = true)
.the paths have to consist only of strong properties,otherwise you are risking crashing the system by not unregistering KVO observer before dealloc.
E.g.
self.rx.observe(CGRect.self,”view.frame”,retainSelf: false)
rx.observeWeakly(rx.observeWeakly has somewhat slower than rx.observe bnecause it has to handle object deallocation in case of weak references.
It can be used in all cases where rx.observe can be used and additionally
.because it won’t retain observed target,it can be used to observe arbitrary object graph whose ownership relation is unknown
.it can be used to observe weak properties
E.g.
someSuspiciousViewController.rx.observeWeakly(Bool.self,”BehavingOk”)
Observing structs(KVO is an Objective-C mechanism so it relies heavily on NSValue.)
RxCocoa has built in support KVO observing of CGRect,CGSize and CGPoint structs.
When observing some other structures it is necessary to extract those tructrues from NSValue manually.Here are examples how to extend KVO observing mechanism and rx.objserve* methods for other structs by implementing KVORepresentable protocol.
UI Layer tips
There are certain things that your observables need to satisfy in the UI layer when binding to UIKit controls.
Threading(Observables need to send values on MainScheduler(UIThread).That’s just a normal UIKit/Cocoa requirement.It it usually a good idea for your apis to return results on MainScheduler.In case you try to bind something to UI from background thread,in Debug build RxCocoa will usually throw an exception to inform you of that.
To fix this you need to add observeOn(MainScheduler.instance).
URLSession extensions don’treturn result on Mainscheduler by default.
Errors(You can’t bind failure to UIKit control because that is undefined behavior.)
If you don’t know if Observable can fail,you can ensure it can’t fail using catchErrorJustReturn(alueThatIsRetrunedWhenErrorHappens),but after an error happens the underlying sequence will still complete.If the wanted behavior is for underlying sequence to continue producing elements,some version of retry operator is needed.
Sharing subscription(You usually want to share subscription in the UI layer.You don’t want to make separate HTTP calls to bind the same data maultiple UI elements.
Let’s say you have something like this:
let searchResults = searchText
.throttle(0.3, $.mainScheduler)
.distinctUntilChanged
.flatMaplatest { query in
API.getSearchResults(query)
.retry(3)
.startWith([])
.catchErrorJustReturn([])
}
.shareReplay(1)
refering to:https://github.com/ReactiveX/RxSwift/blob/master/Documentation/GettingStarted.md#enabling-debug-mode

你可能感兴趣的:(iOS)