RxSwift学习之旅 - 城市搜索

Demo介绍

这是一个通过SearchBar来搜索tableview内容的一个简单的例子,界面如下:

image

mock数据

首先添加一个mock数据到tableview

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//mock数据
var shownCities = [String]() // Data source for UITableView

let allCities = ["ChangSha",
"HangZhou",
"ShangHai",
"BeiJing",
"ShenZhen",
"New York",
"London",
"Oslo",
"Warsaw",
"Berlin",
"Praga"] // Our mocked API data source

//数据源
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, String>>()

dataSource.configureCell = {
(_, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(element)"
return cell
}

获取输入

获取用户的搜索输入,并简单判断前缀来返回结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//获取输入
let searchResult = searchbar.rx
.text
.orEmpty
.flatMapLatest{
[unowned self] query -> Observable<[String]> in
print("\(query)")
if query.isEmpty{
return Observable.just([])
}else{
let results = self.allCities.filter{ $0.hasPrefix(query)}
return Observable.just(results)
}
}
.shareReplay(1)

绑定结果

绑定结果到dataSource:

1
2
3
4
searchResult
.map{ [SectionModel(model:"",items:$0)] }
.bindTo(tableview.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)

现在已经能使用搜索了。

优化

运行后发现每次输入文字,都会发送请求,可以使用debounce指定一段时间后不再有输入再发送请求,同时使用distinctUntilChanged来过滤和上次一样的输入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let searchResult = searchbar.rx
.text
.orEmpty
.debounce(0.5, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest{
[unowned self] query -> Observable<[String]> in
print("\(query)")
if query.isEmpty{
return Observable.just([])
}else{
let results = self.allCities.filter{ $0.hasPrefix(query)}
return Observable.just(results)
}
}
.shareReplay(1)

还可以使用filter直接过滤空的搜索。

1
2
3
4
5
6
7
8
9
10
11
12
let searchResult = searchbar.rx
.text
.orEmpty
.debounce(0.5, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.filter{ !$0.isEmpty }
.flatMapLatest{
[unowned self] query -> Observable<[String]> in
print("\(query)")
return Observable.just(self.allCities.filter{ $0.hasPrefix(query)})
}
.shareReplay(1)

总结

这里主要用到节流来处理用户输入,大家可以结合网络实时从接口获取数据,但是要主要线程切换。

代码见github:

RxSwiftCitySearch

AloneMonkey wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!