绑定
Observable.combineLatest(firstName.rx_text, lastName.rx_text) { $0 + " " + $1 }
.map { "Greetings, \($0)" }
.bindTo(greetingLabel.rx_text)
也可以适用于UITableView
和 UICollectionView
。即使简单的绑定,官方也推荐使用.addDisposableTo(disposeBag)
重试
func doSomethingIncredible(forWho: String) throws -> IncredibleThing
doSomethingIncredible("me")
.retry(3)
抛出错误时可以重试。
代理
self.resultsTableView
.rx_contentOffset
.map { $0.x }
.bindTo(self.leftPositionConstraint.rx_constant)
KVO
使用rx_observe
和 rx_observeWeakly
view.rx_observe(CGRect.self, "frame")
.subscribeNext { frame in
print("Got new frame \(frame)")
}
或者
someSuspiciousViewController
.rx_observeWeakly(Bool.self, "behavingOk")
.subscribeNext { behavingOk in
print("Cats can purr? \(behavingOk)")
}
通知
NSNotificationCenter.defaultCenter()
.rx_notification(UITextViewTextDidBeginEditingNotification, object: myTextView)
.map { /*do something with data*/ }
瞬时状态
- 不必要的请求
- 请求失败
- 延时请求
- 执行请求的时候展示什么
- 重试完也出现错误
searchTextField.rx_text
.throttle(0.3, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query in
API.getSearchResults(query)
.retry(3)
.startWith([]) // clears results on new search term
.catchErrorJustReturn([])
}
.subscribeNext { results in
// bind to ui
}
组合处理
- 可以灵活取消
- 不马上开始
- 限制操作数量
// this is a conceptual solution
let imageSubscription = imageURLs
.throttle(0.2, scheduler: MainScheduler.instance)
.flatMapLatest { imageURL in
API.fetchImage(imageURL)
}
.observeOn(operationScheduler)
.map { imageData in
return decodeAndBlurImage(imageData)
}
.observeOn(MainScheduler.instance)
.subscribeNext { blurredImage in
imageView.image = blurredImage
}
.addDisposableTo(reuseDisposeBag)
合并网络请求
-
zip:合并请求
let userRequest: Observable<User> = API.getUser("me")
let friendsRequest: Observable<Friends> = API.getFriends("me")Observable.zip(userRequest, friendsRequest) { user, friends in return (user, friends) } .subscribeNext { user, friends in // bind them to the user interface }
-
observeOn:切换线程
let userRequest: Observable<User> = API.getUser("me")
let friendsRequest: Observable<[Friend]> = API.getFriends("me")Observable.zip(userRequest, friendsRequest) { user, friends in return (user, friends) } .observeOn(MainScheduler.instance) .subscribeNext { user, friends in // bind them to the user interface }
容易集成
extension NSURLSession {
public func rx_response(request: NSURLRequest) -> Observable<(NSData, NSURLResponse)> {
return Observable.create { observer in
let task = self.dataTaskWithRequest(request) { (data, response, error) in
guard let response = response, data = data else {
observer.on(.Error(error ?? RxCocoaURLError.Unknown))
return
}
guard let httpResponse = response as? NSHTTPURLResponse else {
observer.on(.Error(RxCocoaURLError.NonHTTPResponse(response: response)))
return
}
observer.on(.Next(data, httpResponse))
observer.on(.Completed)
}
task.resume()
return AnonymousDisposable {
task.cancel()
}
}
}
}
好处
- 可以组合的 <- 因为 Rx 是组合的昵称
- 可复用的 <- 因为它是可组合的
- 可声明的 <- 因为定义是不可改变的,而只是数据改变
- 可理解的和简洁的 <- 提高抽象水平并且移除过渡状态
- 稳定的 <- 因为 Rx 代码通过了单元测试
- 更少的状态 <- 因为你是单向数据流的建模应用程序
- 没有泄露 <- 因为资源管理是容易的
In short, using Rx will make your code:
Composable <- Because Rx is composition's nickname
Reusable <- Because it's composable
Declarative <- Because definitions are immutable and only data changes
Understandable and concise <- Raising the level of abstraction and removing transient states
Stable <- Because Rx code is thoroughly unit tested
Less stateful <- Because you are modeling applications as unidirectional data flows
Without leaks <- Because resource management is easy