-
單個(gè)分區(qū)的表格
//創(chuàng)建表格視圖
self.tableView = UITableView(frame: self.view.frame, style:.plain)
//創(chuàng)建一個(gè)重用的單元格
self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.view.addSubview(self.tableView!)
//初始化數(shù)據(jù)
let items = Observable.just([
"文本輸入框的用法",
"開關(guān)按鈕的用法",
"進(jìn)度條的用法",
"文本標(biāo)簽的用法",
])
//設(shè)置單元格數(shù)據(jù)(其實(shí)就是對(duì) 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)
-
單元格選中事件響應(yīng)
//獲取選中項(xiàng)的索引
tableView.rx.itemSelected.subscribe(onNext: { indexPath in
// 取消選中,這句代碼執(zhí)行后不會(huì)觸發(fā) tableView.rx.itemDeselected和tableView.rx.modelDeselected
self.tableView!.deselectRow(at: indexPath, animated: false)
print("選中項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
//獲取選中項(xiàng)的內(nèi)容
tableView.rx.modelSelected(String.self).subscribe(onNext: { item in
print("選中項(xiàng)的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)
// 或者
//獲取選中項(xiàng)的索引
tableView.rx.itemSelected.subscribe(onNext: { [weak self] indexPath in
// 取消選中叙甸,這句代碼執(zhí)行后不會(huì)觸發(fā) tableView.rx.itemDeselected和tableView.rx.modelDeselected
self.tableView!.deselectRow(at: indexPath, animated: false)
self?.showMessage("選中項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
//獲取選中項(xiàng)的內(nèi)容
tableView.rx.modelSelected(String.self).subscribe(onNext: {[weak self] item in
self?.showMessage("選中項(xiàng)的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)
// 合并
Observable.zip(tableView.rx.itemSelected, tableView.rx.modelSelected(String.self))
.bind { [weak self] indexPath, item in
// 取消選中秧耗,這句代碼執(zhí)行后不會(huì)觸發(fā) tableView.rx.itemDeselected和tableView.rx.modelDeselected
self.tableView!.deselectRow(at: indexPath, animated: false)
self?.showMessage("選中項(xiàng)的indexPath為:\(indexPath)")
self?.showMessage("選中項(xiàng)的標(biāo)題為:\(item)")
}
.disposed(by: disposeBag)
-
單元格取消選中事件響應(yīng)
//獲取被取消選中項(xiàng)的索引
tableView.rx.itemDeselected.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("被取消選中項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
//獲取被取消選中項(xiàng)的內(nèi)容
tableView.rx.modelDeselected(String.self).subscribe(onNext: {[weak self] item in
self?.showMessage("被取消選中項(xiàng)的的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)
// 合并
Observable.zip(tableView.rx.itemDeselected, tableView.rx.modelDeselected(String.self))
.bind { [weak self] indexPath, item in
self?.showMessage("被取消選中項(xiàng)的indexPath為:\(indexPath)")
self?.showMessage("被取消選中項(xiàng)的的標(biāo)題為:\(item)")
}
.disposed(by: disposeBag)
-
編輯單元格
編輯單元格時(shí),除了刪除直接實(shí)現(xiàn)下面代碼庐完,可以實(shí)現(xiàn)左滑刪除功能钢属,但不會(huì)在左邊顯示刪除按鈕;其他的操作门躯,都必須使tableView為編輯狀態(tài)淆党,并實(shí)現(xiàn)代理方法,顯示左邊對(duì)應(yīng)的按鈕
self.tableView!.isEditing = true
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .insert
}
-
單元格刪除事件響應(yīng)
//獲取刪除項(xiàng)的索引
tableView.rx.itemDeleted.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("刪除項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
//獲取刪除項(xiàng)的內(nèi)容
tableView.rx.modelDeleted(String.self).subscribe(onNext: {[weak self] item in
self?.showMessage("刪除項(xiàng)的的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)
-
單元格移動(dòng)事件響應(yīng)
//獲取移動(dòng)項(xiàng)的索引
tableView.rx.itemMoved.subscribe(onNext: { [weak self]
sourceIndexPath, destinationIndexPath in
self?.showMessage("移動(dòng)項(xiàng)原來的indexPath為:\(sourceIndexPath)")
self?.showMessage("移動(dòng)項(xiàng)現(xiàn)在的indexPath為:\(destinationIndexPath)")
}).disposed(by: disposeBag)
-
單元格插入事件響應(yīng)
//獲取插入項(xiàng)的索引
tableView.rx.itemInserted.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("插入項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
-
單元格尾部附件(圖標(biāo))點(diǎn)擊事件響應(yīng)
//獲取點(diǎn)擊的尾部圖標(biāo)的索引
tableView.rx.itemAccessoryButtonTapped.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("尾部項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
-
RxDataSources
如果我們的 tableview 需要顯示多個(gè) section、或者更加復(fù)雜的編輯功能時(shí)染乌,可以借助 RxDataSource 這個(gè)第三方庫幫我們完成山孔。
RxDataSource 的本質(zhì)就是使用 RxSwift 對(duì) UITableView 和 UICollectionView 的數(shù)據(jù)源做了一層包裝。使用它可以大大減少我們的工作量
pod 'RxDataSources'
注意:RxDataSources 是以 section 來做為數(shù)據(jù)結(jié)構(gòu)的荷憋。所以不管我們的 tableView 是單分區(qū)還是多分區(qū)台颠,在使用 RxDataSources 的過程中,都需要返回一個(gè) section 的數(shù)組勒庄。
//初始化數(shù)據(jù)
let items = Observable.just([
SectionModel(model: "基本控件", items: [
"UILable的用法",
"UIText的用法",
"UIButton的用法"
]),
SectionModel(model: "高級(jí)控件", items: [
"UITableView的用法",
"UICollectionViews的用法"
])
])
//創(chuàng)建數(shù)據(jù)源
let dataSource = RxTableViewSectionedReloadDataSource
<SectionModel<String, String>>(configureCell: {
(dataSource, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(indexPath.row):\(element)"
})
//設(shè)置分區(qū)頭標(biāo)題
dataSource.titleForHeaderInSection = { ds, index in
return ds.sectionModels[index].model
}
//設(shè)置分區(qū)尾標(biāo)題
dataSource.titleForFooterInSection = { ds, index in
return "footer"
}
//綁定單元格數(shù)據(jù)
items
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
-
數(shù)據(jù)刷新
//隨機(jī)的表格數(shù)據(jù)
let randomResult = refreshButton.rx.tap.asObservable()
.startWith(()) //加這個(gè)為了讓一開始就能自動(dòng)請(qǐng)求一次數(shù)據(jù)
.flatMapLatest{
// 取消請(qǐng)求takeUntil
self.getRandomResult().takeUntil(self.cancelButton.rx.tap)
}
.flatMap(filterResult) //篩選數(shù)據(jù)
.share(replay: 1)
//創(chuàng)建數(shù)據(jù)源
let dataSource = RxTableViewSectionedReloadDataSource
<SectionModel<String, Int>>(configureCell: {
(dataSource, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "條目\(indexPath.row):\(element)"
return cell
})
//綁定單元格數(shù)據(jù)
randomResult
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
//過濾數(shù)據(jù)
func filterResult(data:[SectionModel<String, Int>])
-> Observable<[SectionModel<String, Int>]> {
return self.searchBar.rx.text.orEmpty
//.debounce(0.5, scheduler: MainScheduler.instance) //只有間隔超過0.5秒才發(fā)送
.flatMapLatest{
query -> Observable<[SectionModel<String, Int>]> in
print("正在篩選數(shù)據(jù)(條件為:\(query))")
//輸入條件為空串前,則直接返回原始數(shù)據(jù)
if query.isEmpty{
return Observable.just(data)
}
//輸入條件為不空,則只返回包含有該文字的數(shù)據(jù)
else{
var newData:[SectionModel<String, Int>] = []
for sectionModel in data {
let items = sectionModel.items.filter{ "\($0)".contains(query) }
newData.append(SectionModel(model: sectionModel.model, items: items))
}
return Observable.just(newData)
}
}
}
-
不同類型的單元格混用
//創(chuàng)建數(shù)據(jù)源
let dataSource = RxTableViewSectionedReloadDataSource<MySection>(
//設(shè)置單元格
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
}
},
//設(shè)置分區(qū)頭標(biāo)題
titleForHeaderInSection: { ds, index in
return ds.sectionModels[index].header
}
)
-
樣式修改
修改單元格高度实蔽、設(shè)置組頭組尾荡碾,這些操作RxSwift沒有封裝,所以需要用原始的代理方法來實(shí)現(xiàn)
//設(shè)置代理
tableView.rx.setDelegate(self)
.disposed(by: disposeBag)
參考文章:Swift - RxSwift的使用詳解30(UITableView的使用1:基本用法)
Swift - RxSwift的使用詳解31(UITableView的使用2:RxDataSources)
Swift - RxSwift的使用詳解32(UITableView的使用3:刷新表格數(shù)據(jù))
Swift - RxSwift的使用詳解33(UITableView的使用4:表格數(shù)據(jù)的搜索過濾)
Swift - RxSwift的使用詳解34(UITableView的使用5:可編輯表格)
Swift - RxSwift的使用詳解35(UITableView的使用6:不同類型的單元格混用)
Swift - RxSwift的使用詳解36(UITableView的使用7:樣式修改)