Why(referring to :https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Why.md)
Rx enables building apps in a decalrative way.
Bindings
Observable.combinelatest(firstName.rx.text, lastName.rx.text){ 0+“”+ 1}
.map{ “Greetings, (0)”}
.bind(to: greetingLabel.rx.text)
This Also works with UITableViews and UICollectionViews.
viewModel
.rows
.bind(to: resultsTableView.rx.items(cellIdentifier: “cell”, cellType:WikipediaSearchCell.self)){ (_, viewModel, cell) in
cell.title = viewModel.title
cell.url = viewModel.url
}
.disposed(by: disposeBag)
Official suggestion is to always use .disposed(by: disposeBag) even though that’s not necessary for simple bindings.
Retries
It would be great if APIs wouldn’t fail,but unfortunately they do. Let’s say there is an API method:
func doSomethingIncredible(forWho: String) throws -> IncredibleThing
Ideally,you would want to capture the essence of retrying, and to be able to apply it to any operation.
This is how you can do simple retries with Rx
doSomethingIncredible(“me”)
.retry(3)
You can also easily creat custom retry operators.
Delegate
Instead of doing the tedious and non-expressive:
public func scrollViewDidScroll(scrollView: UIScrollView) { [weak self]// what scroll view is this bound to?
self?.leftPositionConstraint.constant = scrollView.contentOffset.x
}
…write
self.resultsTableView
.rx.contentOffset
.map {0.x }
.bind(to: self.leftPositionConstraint.rx.constant)
and
- (void) observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void *)context
use rx.observe and rx.observeWeakly
this is how they can be used:
view.rx.observe(CGRect.self,”frame”)
.subscribe(onNext: { frame in
print(“Got new frame (frame)”)
})
.disposed(by: disposeBag)
or
someSusipiciousViewController
.rx.observeWeakly(Bool.self, “behavingOK”)
.subscribe(onNext: { behavingOk in
print(“Cats can purr? (behavingOk)”)
})
.disposed(by: disposeBag)
Insteading of using
@available(iOS 4.0, *)
public func addObserverForName(name: String?, object obj: AnyObject?, queue: NSOperationQueue?, usingBlock block: (NSNotification) -> Void) -> NSObjectProtocol
…just write
NotificationCenter.defaul
.rx.notification(NSNotification.name.UITextViewTextDidBeginEditing, object: myTextView)
.map{ }
searchTextField.rx.text
.throttle(0.3, scheduler: MainScheduler.instance)
.distincUntilChanged()
.flatMapLatest { query in
API.getSearchResults(query)
.retry(3)
.startWith([])//clears results on new search term
.catchErrorJustReturn([])
}
.subscribe(onNext: { results in
//bind to ui
})
.disposed(by: disposeBag)
//this is a conceptual solution
let imageSubsription = imageURLs
.throttle(0.2, scheduler: MainScheduler.instance)
.flatMapLatest { imageURL in
API.fetchImage(imageURL)
}
.obseveOn(operationScheduler)
.map { imageData in
return decodeAndBlurImage(imageData)
}
.observeOn(MainScheduler.instance)
.subscribe(onNext: { blurredImage in
imageView.image = blurredImage
})
.disposed(by: reuseDisposeBag)
let userRequest: Observable = API.getUser(“me”)
let friendsRequest: Observable<[Friend]> = API.getFriends(“me”)
Observable.zip(userRequest, friendsRequest) { users, friends in
return(user, friends)
}
.subscribe(onNext: { user, friends in
// bind them to the user interface
})
.disposed(by: disposeBag)
let userRequest: Observable = API.getUser(“me”)
let friendsRequest: Observable<[Friend]> = API.getFriends(“me”)
Observable.zip(userRequest, friendsRequest) { user, friends in
return (user, friends)
}
.observeOn(MainScheduler.instance)
.subscribe(onNext: {user, friends in
//bind them to the user interface
})
.disposed(by: disposeBag)
extension Reative where Base: URLSession {
public func response(request: URLRequest)) -> Observable<(Data, HTTPURLResponse)> {
return Observable.create { observer in
let task = self.base.dataTask(wih: request)) {(data, reponse,error) in
guard let reponse = reponse, let data = data else {
observer.on(.error(error ?? RxCocoaURLError.unknown))
return
}
guard let httpResponse = response as? HTTPURLResponse else {
observer.on(.error(RxCocoaURLError.nonHttpResponse(reponse: response)))
return
}
observer.on(.next(data, httpResponse))
observer.on(.completed)
}
task.resume()
return Disposables.create(with: task.cancel)
}
}
}