在一个ViewModel里面有一个data属性,类型为Driver<[Repository]>,它用于发起网络请求,代码如下:
struct ViewModel {
let searchText = Variable("")
let disposeBag = DisposeBag()
lazy var data: Driver<[Repository]> = {
return self.searchText.asObservable()
.throttle(0.3, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest {
self.getRepositories($0)
}
.asDriver(onErrorJustReturn: [])
}()
....
}
- 在 ViewController 里把 UISearchBar 和 searchText 进行绑定,然后通过 data 和 UITableView 进行绑定,当 SearchBar 的 text 发现改变就触发网络请求,
self.getRepositories($0)
,返回一个Observable<[Repository]>
func getRepositories(gitHubID: String) -> Observable<[Repository]> {
guard !gitHubID.isEmpty,
let url = NSURL(string: "https://api.github.com/users/\(gitHubID)/repos")
else { return Observable.just([]) }
return NSURLSession.sharedSession()
.rx_JSON(NSURLRequest(URL: url))
.debug()
.retry(3)
// .catchErrorJustReturn([])
.map {
var repositories = [Repository]()
if let items = $0 as? [[String: AnyObject]] {
items.forEach {
guard let name = $0["name"] as? String,
url = $0["html_url"] as? String
else { return }
repositories.append(Repository(name: name, url: url))
}
}
return repositories
}
}
但是这里会有一个问题,如果 rx_JSON
这里发射出一个Error,会导致data这个事件流后面被 dispose 了,然后后面在 SearchBar 中输入任何内容都不会执行, 可以在 retry 后面加上 .catchErrorJustReturn([]) 当遇到错误的时候返回 [], 当发生Error 的时候,不发射出 Error,而是发射出一个 [],所以当出现错误的时候,最终data的事件流中,不会出现Error事件,如果出现 Error 事件的时候被返回了 [],如果没有加 .catchErrorJustReturn([])的情况下,会导致 data 的事件流中接收到 Error,导致事件流被 dispose 了。