下面只是来分析其中的主要内容:
import UIKit
import RxCocoa
import RxSwift
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var searchBar: UISearchBar!
var shownCities = [String]() //
let allCities = ["New York", "London", "Oslo", "Warsaw", "Berlin", "Praga"] // Our mocked API data source
let disposeBag = DisposeBag() // Bag of disposables to release them when view is being deallocated
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
func setup() {
tableView.dataSource = self
searchBar
.rx.text // Observable property thanks to RxCocoa
.orEmpty // Make it non-optional
.debounce(0.5, scheduler: MainScheduler.instance) // Wait 0.5 for changes.
.distinctUntilChanged() // If they didn't occur, check if the new value is the same as old.
.filter { !$0.isEmpty } // If the new value is really new, filter for non-empty query.
.subscribe(onNext: { [unowned self] query in // Here we subscribe to every new value, that is not empty (thanks to filter above).
self.shownCities = self.allCities.filter { $0.hasPrefix(query) } // We now do our "API Request" to find cities.
self.tableView.reloadData() // And reload table view data.
})
.addDisposableTo(disposeBag) // Don't forget to add this to disposeBag. We want to dispose it on deinit.
}
}
// MARK: - UITableViewDataSource
/// Here we have standard data source extension for ViewController
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return shownCities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cityPrototypeCell", for: indexPath)
cell.textLabel?.text = shownCities[indexPath.row]
return cell
}
}
这段代码的目的是演示 Rx 中的主体内容: 观察者, Observable 序列, 以及若干操作符.
代码的主要功能是: 当用户在输入框输入想要查询的地址时, 可以根据输入来动态显示对应的城市列表.
首先定义了两个属性, 一个属性用于存放所有的城市allCities
, 一个属性用于存放当前显示的城市shownCities
.
这里选择的观察时机是在 viewDidLoad 中, 在其中调用 setup()
方法, 下面就主要来看这个方法中的内容:
func setup() {
// 指定 tableView 的数据源.
tableView.dataSource = self
searchBar
.rx.text
.orEmpty
.debounce(0.5, scheduler: MainScheduler.instance)
.distinctUntilChanged() // If they didn't occur, check if the new value is the same as old.
.filter { !$0.isEmpty } // If the new value is really new, filter for non-empty query.
.subscribe(onNext: { [unowned self] query in // Here we subscribe to every new value, that is not empty (thanks to filter above).
self.shownCities = self.allCities.filter { $0.hasPrefix(query) } // We now do our "API Request" to find cities.
self.tableView.reloadData() // And reload table view data.
})
.addDisposableTo(disposeBag) // Don't forget to add this to disposeBag. We want to dispose it on deinit.
}
- .rx.text 是 RxCocoa 对 UI 组件的 Rx 扩展属性, 这种属性实际是一种特殊的 Observable 类型
ControlProperty
. - orEmpty 操作符也是 RxCocoa 提供的. 其作用是如果遇到 nil, 则解包为默认值, 比如字符串的话就解包为空字符串, 如果非空就进行正常解包.
-
debounce(dueTime: RxTimeInterval, scheduler: SchedulerType)
操作符是在 RxSwift 中定义的, 它的作用是在序列上按指定时间间隔进行过滤, 只有大于时间间隔的元素才会通过. 而 scheduler 指定计时器是在哪个线程上执行. 而 MainScheduler.instance 获取的是主线程的单例对象, MainScheduler 类似于 DispatchQueue.main.
而实际上 debounce 的作用是去抖动, 即指定的时长是一个阈值, 只有当超过这个阈值, 而序列没有再次发生变化的时候, 才会让元素继续通过. 比如用户一直很快点击键盘, 此时每次停留的间隔小于 0.5 秒, 则元素一直不会被允许通过. 只有当用户输入暂停的时候, 才会将元素通过. - distinctUntilChanged 操作符也是在 RxSwift 中定义的, 作用是从源序列中生成一个新的序列, 该序列是通过判等来将相同元素过滤掉形成的.
- filter 操作符在 RxSwift 中定义, 作用和 swift 的 filter 操作符类似, 进行过滤, 让满足条件的元素通过.
- 再下面就是进行观察操作了.
网友评论