-
单个分区的表格
//创建表格视图
self.tableView = UITableView(frame: self.view.frame, style:.plain)
//创建一个重用的单元格
self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.view.addSubview(self.tableView!)
//初始化数据
let items = Observable.just([
"文本输入框的用法",
"开关按钮的用法",
"进度条的用法",
"文本标签的用法",
])
//设置单元格数据(其实就是对 cellForRowAt 的封装)
items
.bind(to: tableView.rx.items) { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(row):\(element)"
return cell
}
.disposed(by: disposeBag)
// 或者拆开写为
let bibao = items.bind(to: (tableView?.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self))!)
bibao {
(row, element, cell) in
cell.textLabel?.text = "\(row):\(element)"
}.disposed(by: disposeBag)
-
单元格选中事件响应
//获取选中项的索引
tableView.rx.itemSelected.subscribe(onNext: { indexPath in
// 取消选中,这句代码执行后不会触发 tableView.rx.itemDeselected和tableView.rx.modelDeselected
self.tableView!.deselectRow(at: indexPath, animated: false)
print("选中项的indexPath为:\(indexPath)")
}).disposed(by: disposeBag)
//获取选中项的内容
tableView.rx.modelSelected(String.self).subscribe(onNext: { item in
print("选中项的标题为:\(item)")
}).disposed(by: disposeBag)
// 或者
//获取选中项的索引
tableView.rx.itemSelected.subscribe(onNext: { [weak self] indexPath in
// 取消选中,这句代码执行后不会触发 tableView.rx.itemDeselected和tableView.rx.modelDeselected
self.tableView!.deselectRow(at: indexPath, animated: false)
self?.showMessage("选中项的indexPath为:\(indexPath)")
}).disposed(by: disposeBag)
//获取选中项的内容
tableView.rx.modelSelected(String.self).subscribe(onNext: {[weak self] item in
self?.showMessage("选中项的标题为:\(item)")
}).disposed(by: disposeBag)
// 合并
Observable.zip(tableView.rx.itemSelected, tableView.rx.modelSelected(String.self))
.bind { [weak self] indexPath, item in
// 取消选中,这句代码执行后不会触发 tableView.rx.itemDeselected和tableView.rx.modelDeselected
self.tableView!.deselectRow(at: indexPath, animated: false)
self?.showMessage("选中项的indexPath为:\(indexPath)")
self?.showMessage("选中项的标题为:\(item)")
}
.disposed(by: disposeBag)
-
单元格取消选中事件响应
//获取被取消选中项的索引
tableView.rx.itemDeselected.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("被取消选中项的indexPath为:\(indexPath)")
}).disposed(by: disposeBag)
//获取被取消选中项的内容
tableView.rx.modelDeselected(String.self).subscribe(onNext: {[weak self] item in
self?.showMessage("被取消选中项的的标题为:\(item)")
}).disposed(by: disposeBag)
// 合并
Observable.zip(tableView.rx.itemDeselected, tableView.rx.modelDeselected(String.self))
.bind { [weak self] indexPath, item in
self?.showMessage("被取消选中项的indexPath为:\(indexPath)")
self?.showMessage("被取消选中项的的标题为:\(item)")
}
.disposed(by: disposeBag)
-
编辑单元格
编辑单元格时,除了删除直接实现下面代码,可以实现左滑删除功能,但不会在左边显示删除按钮;其他的操作,都必须使tableView为编辑状态,并实现代理方法,显示左边对应的按钮
self.tableView!.isEditing = true
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .insert
}
-
单元格删除事件响应
//获取删除项的索引
tableView.rx.itemDeleted.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("删除项的indexPath为:\(indexPath)")
}).disposed(by: disposeBag)
//获取删除项的内容
tableView.rx.modelDeleted(String.self).subscribe(onNext: {[weak self] item in
self?.showMessage("删除项的的标题为:\(item)")
}).disposed(by: disposeBag)
-
单元格移动事件响应
//获取移动项的索引
tableView.rx.itemMoved.subscribe(onNext: { [weak self]
sourceIndexPath, destinationIndexPath in
self?.showMessage("移动项原来的indexPath为:\(sourceIndexPath)")
self?.showMessage("移动项现在的indexPath为:\(destinationIndexPath)")
}).disposed(by: disposeBag)
-
单元格插入事件响应
//获取插入项的索引
tableView.rx.itemInserted.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("插入项的indexPath为:\(indexPath)")
}).disposed(by: disposeBag)
-
单元格尾部附件(图标)点击事件响应
//获取点击的尾部图标的索引
tableView.rx.itemAccessoryButtonTapped.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("尾部项的indexPath为:\(indexPath)")
}).disposed(by: disposeBag)
-
RxDataSources
如果我们的 tableview 需要显示多个 section、或者更加复杂的编辑功能时,可以借助 RxDataSource 这个第三方库帮我们完成。
RxDataSource 的本质就是使用 RxSwift 对 UITableView 和 UICollectionView 的数据源做了一层包装。使用它可以大大减少我们的工作量
pod 'RxDataSources'
注意:RxDataSources 是以 section 来做为数据结构的。所以不管我们的 tableView 是单分区还是多分区,在使用 RxDataSources 的过程中,都需要返回一个 section 的数组。
//初始化数据
let items = Observable.just([
SectionModel(model: "基本控件", items: [
"UILable的用法",
"UIText的用法",
"UIButton的用法"
]),
SectionModel(model: "高级控件", items: [
"UITableView的用法",
"UICollectionViews的用法"
])
])
//创建数据源
let dataSource = RxTableViewSectionedReloadDataSource
>(configureCell: {
(dataSource, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(indexPath.row):\(element)"
})
//设置分区头标题
dataSource.titleForHeaderInSection = { ds, index in
return ds.sectionModels[index].model
}
//设置分区尾标题
dataSource.titleForFooterInSection = { ds, index in
return "footer"
}
//绑定单元格数据
items
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
-
数据刷新
//随机的表格数据
let randomResult = refreshButton.rx.tap.asObservable()
.startWith(()) //加这个为了让一开始就能自动请求一次数据
.flatMapLatest{
// 取消请求takeUntil
self.getRandomResult().takeUntil(self.cancelButton.rx.tap)
}
.flatMap(filterResult) //筛选数据
.share(replay: 1)
//创建数据源
let dataSource = RxTableViewSectionedReloadDataSource
>(configureCell: {
(dataSource, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "条目\(indexPath.row):\(element)"
return cell
})
//绑定单元格数据
randomResult
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
//过滤数据
func filterResult(data:[SectionModel])
-> Observable<[SectionModel]> {
return self.searchBar.rx.text.orEmpty
//.debounce(0.5, scheduler: MainScheduler.instance) //只有间隔超过0.5秒才发送
.flatMapLatest{
query -> Observable<[SectionModel]> in
print("正在筛选数据(条件为:\(query))")
//输入条件为空,则直接返回原始数据
if query.isEmpty{
return Observable.just(data)
}
//输入条件为不空,则只返回包含有该文字的数据
else{
var newData:[SectionModel] = []
for sectionModel in data {
let items = sectionModel.items.filter{ "\($0)".contains(query) }
newData.append(SectionModel(model: sectionModel.model, items: items))
}
return Observable.just(newData)
}
}
}
-
不同类型的单元格混用
//创建数据源
let dataSource = RxTableViewSectionedReloadDataSource(
//设置单元格
configureCell: { dataSource, tableView, indexPath, item in
switch dataSource[indexPath] {
case let .TitleImageSectionItem(title, image):
let cell = tableView.dequeueReusableCell(withIdentifier: "titleImageCell",
for: indexPath)
(cell.viewWithTag(1) as! UILabel).text = title
(cell.viewWithTag(2) as! UIImageView).image = image
return cell
case let .TitleSwitchSectionItem(title, enabled):
let cell = tableView.dequeueReusableCell(withIdentifier: "titleSwitchCell",
for: indexPath)
(cell.viewWithTag(1) as! UILabel).text = title
(cell.viewWithTag(2) as! UISwitch).isOn = enabled
return cell
}
},
//设置分区头标题
titleForHeaderInSection: { ds, index in
return ds.sectionModels[index].header
}
)
-
样式修改
修改单元格高度、设置组头组尾,这些操作RxSwift没有封装,所以需要用原始的代理方法来实现
//设置代理
tableView.rx.setDelegate(self)
.disposed(by: disposeBag)
参考文章:Swift - RxSwift的使用详解30(UITableView的使用1:基本用法)
Swift - RxSwift的使用详解31(UITableView的使用2:RxDataSources)
Swift - RxSwift的使用详解32(UITableView的使用3:刷新表格数据)
Swift - RxSwift的使用详解33(UITableView的使用4:表格数据的搜索过滤)
Swift - RxSwift的使用详解34(UITableView的使用5:可编辑表格)
Swift - RxSwift的使用详解35(UITableView的使用6:不同类型的单元格混用)
Swift - RxSwift的使用详解36(UITableView的使用7:样式修改)