日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RxSwift之UI控件UITableView扩展的使用

發布時間:2024/5/21 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RxSwift之UI控件UITableView扩展的使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、基本使用

① 單分區的表格

  • 如下所示,單個分區的表格展示:

  • 示例代碼:
import UIKit import RxSwift import RxCocoaclass ViewController: UIViewController {var tableView:UITableView!let disposeBag = DisposeBag()override func viewDidLoad() {super.viewDidLoad()// 創建表格視圖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) inlet cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!cell.textLabel?.text = "\(row)\(element)"return cell}.disposed(by: disposeBag)} }

② 單元格選中事件響應

  • 當點擊某個單元格時將其索引位置,以及對應的標題打印出來:

選中項的indexPath為:[0, 3] 選中項的標題為:文本標簽的用法
  • 業務代碼直接放在響應方法內部,示例代碼:
// 獲取選中項的索引 tableView.rx.itemSelected.subscribe(onNext: { indexPath inprint("選中項的indexPath為:\(indexPath)") }).disposed(by: disposeBag)// 獲取選中項的內容 tableView.rx.modelSelected(String.self).subscribe(onNext: { item inprint("選中項的標題為:\(item)") }).disposed(by: disposeBag)
  • 也可以在響應中調用外部的方法:
// 獲取選中項的索引 tableView.rx.itemSelected.subscribe(onNext: { [weak self] indexPath inprint("選中項的indexPath為:\(indexPath)") }).disposed(by: disposeBag)// 獲取選中項的內容 tableView.rx.modelSelected(String.self).subscribe(onNext: {[weak self] item inprint("選中項的標題為:\(item)") }).disposed(by: disposeBag)

③ 單元格取消選中事件響應

被取消選中項的indexPath為:[0, 2] 被取消選中項的的標題為:進度條的用法
  • 示例代碼:
// 獲取被取消選中項的索引 tableView.rx.itemDeselected.subscribe(onNext: { [weak self] indexPath inprint("被取消選中項的indexPath為:\(indexPath)") }).disposed(by: disposeBag)// 獲取被取消選中項的內容 tableView.rx.modelDeselected(String.self).subscribe(onNext: {[weak self] item inprint("被取消選中項的的標題為:\(item)") }).disposed(by: disposeBag)

④ 單元格刪除事件響應

  • 如下所示,左滑刪除:
  • 示例代碼:
// 獲取刪除項的索引 tableView.rx.itemDeleted.subscribe(onNext: { indexPath inprint("刪除項的indexPath為:\(indexPath)") }).disposed(by: disposeBag)// 獲取刪除項的內容 tableView.rx.modelDeleted(String.self).subscribe(onNext: {item inprint("刪除項的的標題為:\(item)") }).disposed(by: disposeBag)

⑤ 單元格移動事件響應

移動項原來的indexPath為:[0, 0] 移動項現在的indexPath為:[0, 1]
  • 示例代碼:
// 獲取移動項的索引 tableView.rx.itemMoved.subscribe(onNext: {sourceIndexPath, destinationIndexPath inprint("移動項原來的indexPath為:\(sourceIndexPath)")print("移動項現在的indexPath為:\(destinationIndexPath)") }).disposed(by: disposeBag)

⑥ 單元格插入事件響應

插入項的indexPath為:[0, 1]
  • 示例代碼:
// 獲取插入項的索引 tableView.rx.itemInserted.subscribe(onNext: { indexPath inprint("插入項的indexPath為:\(indexPath)") }).disposed(by: disposeBag)

⑦ 單元格尾部附件(圖標)點擊事件響應

尾部項的indexPath為:[0, 1]
  • 示例代碼:
// 獲取點擊的尾部圖標的索引 tableView.rx.itemAccessoryButtonTapped.subscribe(onNext: { indexPath inprint("尾部項的indexPath為:\(indexPath)") }).disposed(by: disposeBag)

⑧ 單元格將要顯示出來的事件響應

  • 如下所示:
將要顯示單元格indexPath為:[0, 0] 將要顯示單元格cell為:<UITableViewCell: 0x7fe74e925fd0; frame = (0 0; 428 45); text = '0:文本輸入框的用法'; autoresize = W; layer = <CALayer: 0x600003d77560>>將要顯示單元格indexPath為:[0, 1] 將要顯示單元格cell為:<UITableViewCell: 0x7fe74eb16080; frame = (0 45; 428 45); text = '1:開關按鈕的用法'; autoresize = W; layer = <CALayer: 0x600003d12de0>>將要顯示單元格indexPath為:[0, 2] 將要顯示單元格cell為:<UITableViewCell: 0x7fe74ea0b1b0; frame = (0 90; 428 45); text = '2:進度條的用法'; autoresize = W; layer = <CALayer: 0x600003d1a700>>將要顯示單元格indexPath為:[0, 3] 將要顯示單元格cell為:<UITableViewCell: 0x7fe74ea0c670; frame = (0 135; 428 45); text = '3:文本標簽的用法'; autoresize = W; layer = <CALayer: 0x600003d1a9e0>>
  • 示例代碼:
// 獲取選中項的索引 tableView.rx.willDisplayCell.subscribe(onNext: { cell, indexPath inprint("將要顯示單元格indexPath為:\(indexPath)")print("將要顯示單元格cell為:\(cell)\n") }).disposed(by: disposeBag)

二、RxDataSources

  • 如果 tableview 需要顯示多個 section 或者更加復雜的編輯功能時,可以借助 RxDataSource 這個第三方庫來幫我們完成。
  • RxDataSource 的本質就是使用 RxSwift 對 UITableView 和 UICollectionView 的數據源做了一層包裝,使用它可以大大減少我們的工作量。

① 安裝配置

  • CocoaPods:
pod 'RxDataSources', '~> 3.0'
  • Carthage
github "RxSwiftCommunity/RxDataSources" ~> 3.0
  • 手動安裝:
    • 在 RxDataSources 上將 RxDataSources 下載到本地,并引入到項目中來:

    • 在代碼中將其 import 進來即可:
import RxDataSources

② 單分區的 TableView

  • 現在需要實現如下效果:

  • RxDataSources 是以 section 來做為數據結構的,所以不管 tableView 是單分區還是多分區,在使用 RxDataSources 的過程中,都需要返回一個 section 的數組。
  • 使用自帶的 Section:
// 創建表格視圖 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([SectionModel(model: "", items: ["UILable的用法","UIText的用法","UIButton的用法"])])// 創建數據源 let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, String>>(configureCell: {(dataSource, tv, indexPath, element) inlet cell = tv.dequeueReusableCell(withIdentifier: "Cell")!cell.textLabel?.text = "\(indexPath.row)\(element)"return cell})// 綁定單元格數據 items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: DisposeBag())
  • 使用自定義的 Section:
// 創建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創建一個重用的單元格 self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 初始化數據 let sections = Observable.just([MySection(header: "", items: ["UILable的用法","UIText的用法","UIButton的用法"])])// 創建數據源 let dataSource = RxTableViewSectionedAnimatedDataSource<MySection>(// 設置單元格configureCell: { ds, tv, ip, item inlet cell = tv.dequeueReusableCell(withIdentifier: "Cell")?? UITableViewCell(style: .default, reuseIdentifier: "Cell")cell.textLabel?.text = "\(ip.row)\(item)"return cell })// 綁定單元格數據 sections.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: DisposeBag())// 自定義Section struct MySection {var header: Stringvar items: [Item] }extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity: String {return header}init(original: MySection, items: [Item]) {self = originalself.items = items} }

③ 多分區的 UITableView

  • 現在要實現如下效果:

  • 使用自帶的 Section:
// 創建表格視圖 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([SectionModel(model: "基本控件", items: ["UILable的用法","UIText的用法","UIButton的用法"]),SectionModel(model: "高級控件", items: ["UITableView的用法","UICollectionViews的用法"])])// 創建數據源 let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, String>>(configureCell: {(dataSource, tv, indexPath, element) inlet cell = tv.dequeueReusableCell(withIdentifier: "Cell")!cell.textLabel?.text = "\(indexPath.row)\(element)"return cell })// 設置分區頭標題 dataSource.titleForHeaderInSection = { ds, index inreturn ds.sectionModels[index].model }// 設置分區尾標題 //dataSource.titleForFooterInSection = { ds, index in // return "footer" //}// 綁定單元格數據 items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)
  • 使用自定義的 Section:
// 創建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創建一個重用的單元格 self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 初始化數據 let sections = Observable.just([MySection(header: "基本控件", items: ["UILable的用法","UIText的用法","UIButton的用法"]),MySection(header: "高級控件", items: ["UITableView的用法","UICollectionViews的用法"])])// 創建數據源 let dataSource = RxTableViewSectionedAnimatedDataSource<MySection>(// 設置單元格configureCell: { ds, tv, ip, item inlet cell = tv.dequeueReusableCell(withIdentifier: "Cell")?? UITableViewCell(style: .default, reuseIdentifier: "Cell")cell.textLabel?.text = "\(ip.row)\(item)"return cell},// 設置分區頭標題titleForHeaderInSection: { ds, index inreturn ds.sectionModels[index].header}// 自定義Section struct MySection {var header: Stringvar items: [Item] }extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity: String {return header}init(original: MySection, items: [Item]) {self = originalself.items = items} }

三、刷新表格數據

  • 很多情況下,表格里的數據不是一開始就準備好的、或者固定不變的,可能需要先向服務器請求數據,再將獲取到的內容顯示在表格中。
  • 要重新加載表格數據,過去的做法就是調用 tableView 的 reloadData() 方法,那么在使用 RxSwift 的情況下,應該如何刷新表格的數據呢?

① 數據刷新

  • 如下所示:
    • 界面初始化完畢后,tableView 默認會加載一些隨機數據;
    • 點擊右上角的刷新按鈕,tableView 會重新加載并顯示一批新數據;
    • 為方便演示,每次獲取數據不是真的去發起網絡請求,而是在本地生成后延遲 2 秒返回,模擬這種異步請求的情況。

  • 示例代碼:
// 創建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創建一個重用的單元格 self.tableView!.register(UITableViewCell.self,forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 隨機的表格數據 let randomResult = refreshButton.rx.tap.asObservable().startWith(()) // 為了一開始就能自動請求一次數據.flatMapLatest(getRandomResult).share(replay: 1)// 創建數據源 let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Int>>(configureCell: {(dataSource, tv, indexPath, element) inlet 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 getRandomResult() -> Observable<[SectionModel<String, Int>]> {print("正在請求數據...")let items = (0 ..< 5).map {_ inInt(arc4random())}let observable = Observable.just([SectionModel(model: "S", items: items)])return observable.delay(2, scheduler: MainScheduler.instance) }

② 防止表格多次刷新

  • flatMapLatest 的作用是當在短時間內(上一個請求還沒回來)連續點擊多次“刷新”按鈕,雖然仍會發起多次請求,但表格只會接收并顯示最后一次請求,避免表格出現連續刷新的現象:
// 隨機的表格數據 let randomResult = refreshButton.rx.tap.asObservable().startWith(()) // 為了一開始就能自動請求一次數據.flatMapLatest(getRandomResult).share(replay: 1)
  • 也可以對源頭進行限制,即通過 throttle 設置個閥值(比如 1 秒),如果在1秒內有多次點擊則只取最后一次,那么自然也就只發送一次數據請求:
// 隨機的表格數據 let randomResult = refreshButton.rx.tap.asObservable().throttle(1, scheduler: MainScheduler.instance) // 在主線程中操作,1秒內值若多次改變,取最后一次.startWith(()) // 為了一開始就能自動請求一次數據.flatMapLatest(getRandomResult).share(replay: 1)

③ 停止數據請求

  • 在實際項目中我們可能會需要對一個未完成的網絡請求進行中斷操作,比如切換頁面或者分類時,如果上一次的請求還未完成就要將其取消掉。那么 RxSwift 如何實現該功能呢?
  • 該功能簡單說就是通過 takeUntil 操作符實現,當 takeUntil 中的 Observable 發送一個值時,便會結束對應的 Observable:
// 創建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創建一個重用的單元格 self.tableView!.register(UITableViewCell.self,forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 隨機的表格數據 let randomResult = refreshButton.rx.tap.asObservable().startWith(()) // 為一開始就能自動請求一次數據.flatMapLatest{self.getRandomResult().takeUntil(self.cancelButton.rx.tap)}.share(replay: 1)// 創建數據源 let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Int>>(configureCell: {(dataSource, tv, indexPath, element) inlet 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 getRandomResult() -> Observable<[SectionModel<String, Int>]> {print("正在請求數據......")let items = (0 ..< 5).map {_ inInt(arc4random())}let observable = Observable.just([SectionModel(model: "S", items: items)])return observable.delay(2, scheduler: MainScheduler.instance) }

四、表格數據的搜索過濾

  • 在 tableView 的表頭上增加了一個搜索框,tableView 會根據搜索框里輸入的內容實時地篩選并顯示出符合條件的數據(包含有輸入文字的數據條目)。
  • 這個實時搜索是對已獲取到的數據進行過濾,即每次輸入文字時不會重新發起請求。


  • 示例代碼:
// 創建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創建一個重用的單元格 self.tableView!.register(UITableViewCell.self,forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 創建表頭的搜索欄 self.searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: 56)) self.tableView.tableHeaderView = self.searchBar// 隨機的表格數據 let randomResult = refreshButton.rx.tap.asObservable().startWith(()) // 為一開始就能自動請求一次數據.flatMapLatest(getRandomResult) // 獲取數據.flatMap(filterResult) // 篩選數據.share(replay: 1)// 創建數據源 let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Int>>(configureCell: {(dataSource, tv, indexPath, element) inlet 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 getRandomResult() -> Observable<[SectionModel<String, Int>]> {print("正在請求數據...")let items = (0 ..< 5).map {_ inInt(arc4random())}let observable = Observable.just([SectionModel(model: "S", items: items)])return observable.delay(2, scheduler: MainScheduler.instance) }// 過濾數據 func filterResult(data:[SectionModel<String, Int>]) -> Observable<[SectionModel<String, Int>]> {return self.searchBar.rx.text.orEmpty//.debounce(0.5, scheduler: MainScheduler.instance) //只有間隔超過0.5秒才發送.flatMapLatest{query -> Observable<[SectionModel<String, Int>]> inprint("正在篩選數據(條件為:\(query))")// 輸入條件為空,則直接返回原始數據if query.isEmpty{return Observable.just(data)}// 輸入條件為不空,則只返回包含有該文字的數據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)}} }

五、可編輯表格

① 實現效果

  • 程序啟動后表格會自動加載 5 條隨機數據,點擊“刷新”按鈕則又重新生成 5 條數據并顯示;
  • 點擊“加號”圖標后,會在當前數據集的末尾添加一條隨機數據并顯示;
  • 點擊單元格左側的“減號”圖標則可以將該行數據刪除;
  • 拖動單元格右側的控制圖標可以改變顯示順序。


② 示例代碼

  • 由于編輯操作比較多,使用 enum 創建一個命令枚舉,里面定義了對 tableView 數據的各種操作:
// 定義各種操作命令 enum TableEditingCommand {case setItems(items: [String]) // 設置表格數據case addItem(item: String) // 新增數據case moveItem(from: IndexPath, to: IndexPath) // 移動數據case deleteItem(IndexPath) // 刪除數據 }
  • 接著定義 tableView 對應的 ViewModel,這里面除了保存有表格數據外,還包含上面定義的 4 個操作命令的具體實現:
// 定義表格對應的ViewModel struct TableViewModel {// 表格數據項fileprivate var items:[String]init(items: [String] = []) {self.items = items}// 執行相應的命令,并返回最終的結果func execute(command: TableEditingCommand) -> TableViewModel {switch command {case .setItems(let items):print("設置表格數據。")return TableViewModel(items: items)case .addItem(let item):print("新增數據項。")var items = self.itemsitems.append(item)return TableViewModel(items: items)case .moveItem(let from, let to):print("移動數據項。")var items = self.itemsitems.insert(items.remove(at: from.row), at: to.row)return TableViewModel(items: items)case .deleteItem(let indexPath):print("刪除數據項。")var items = self.itemsitems.remove(at: indexPath.row)return TableViewModel(items: items)}} }
  • 主視圖控制器代碼:
class ViewController: UIViewController {// 刷新按鈕@IBOutlet weak var refreshButton: UIBarButtonItem!// 新增按鈕@IBOutlet weak var addButton: UIBarButtonItem!// 表格var tableView:UITableView!let disposeBag = DisposeBag()override func viewDidLoad() {super.viewDidLoad()// 創建表格視圖self.tableView = UITableView(frame: self.view.frame, style:.plain)// 創建一個重用的單元格self.tableView!.register(UITableViewCell.self,forCellReuseIdentifier: "Cell")self.view.addSubview(self.tableView!)// 表格模型let initialVM = TableViewModel()// 刷新數據命令let refreshCommand = refreshButton.rx.tap.asObservable().startWith(()).flatMapLatest(getRandomResult).map(TableEditingCommand.setItems)// 新增條目命令let addCommand = addButton.rx.tap.asObservable().map{ "\(arc4random())" }.map(TableEditingCommand.addItem)// 移動位置命令let movedCommand = tableView.rx.itemMoved.map(TableEditingCommand.moveItem)// 刪除條目命令let deleteCommand = tableView.rx.itemDeleted.asObservable().map(TableEditingCommand.deleteItem)// 綁定單元格數據Observable.of(refreshCommand, addCommand, movedCommand, deleteCommand).merge().scan(initialVM) { (vm: TableViewModel, command: TableEditingCommand)-> TableViewModel inreturn vm.execute(command: command)}.startWith(initialVM).map {[AnimatableSectionModel(model: "", items: $0.items)]}.share(replay: 1).bind(to: tableView.rx.items(dataSource: ViewController.dataSource())).disposed(by: disposeBag)}override func viewDidAppear(_ animated: Bool) {super.viewDidAppear(animated)tableView.setEditing(true, animated: true)}// 獲取隨機數據func getRandomResult() -> Observable<[String]> {print("生成隨機數據。")let items = (0 ..< 5).map {_ in"\(arc4random())"}return Observable.just(items)} }extension ViewController {// 創建表格數據源static func dataSource() -> RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<String, String>> {return RxTableViewSectionedAnimatedDataSource(// 設置插入、刪除、移動單元格的動畫效果animationConfiguration: AnimationConfiguration(insertAnimation: .top,reloadAnimation: .fade,deleteAnimation: .left),configureCell: {(dataSource, tv, indexPath, element) inlet cell = tv.dequeueReusableCell(withIdentifier: "Cell")!cell.textLabel?.text = "條目\(indexPath.row)\(element)"return cell},canEditRowAtIndexPath: { _, _ inreturn true // 單元格可刪除},canMoveRowAtIndexPath: { _, _ inreturn true // 單元格可移動})} }

六、不同類型的單元格混用

① 效果展示

  • tableView 綁定的數據源中一共有 2 個 section,每個 section 里分別有 3 條數據需要顯示。
  • 每個 cell 會根據數據類型的不同,自動選擇相應的顯示方式:“文字+圖片”或“文字+開關按鈕”。

② 示例代碼

// 初始化數據 let sections = Observable.just([MySection(header: "我是第一個分區", items: [.TitleImageSectionItem(title: "圖片數據1", image: UIImage(named: "php")!),.TitleImageSectionItem(title: "圖片數據2", image: UIImage(named: "react")!),.TitleSwitchSectionItem(title: "開關數據1", enabled: true)]),MySection(header: "我是第二個分區", items: [.TitleSwitchSectionItem(title: "開關數據2", enabled: false),.TitleSwitchSectionItem(title: "開關數據3", enabled: false),.TitleImageSectionItem(title: "圖片數據3", image: UIImage(named: "swift")!)])])// 創建數據源 let dataSource = RxTableViewSectionedReloadDataSource<MySection>(// 設置單元格configureCell: { dataSource, tableView, indexPath, item inswitch 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 = imagereturn cellcase 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 = enabledreturn cell}},// 設置分區頭標題titleForHeaderInSection: { ds, index inreturn ds.sectionModels[index].header} )// 綁定單元格數據 sections.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)// 單元格類型 enum SectionItem {case TitleImageSectionItem(title: String, image: UIImage)case TitleSwitchSectionItem(title: String, enabled: Bool) }// 自定義Section struct MySection {var header: Stringvar items: [SectionItem] }extension MySection : SectionModelType {typealias Item = SectionIteminit(original: MySection, items: [Item]) {self = originalself.items = items} }

七、UITableView 相關樣式的修改

① 修改單元格高度

  • 示例代碼:
var tableView:UITableView! var dataSource:RxTableViewSectionedAnimatedDataSource<MySection>? let disposeBag = DisposeBag()// 創建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創建一個重用的單元格 self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 初始化數據 let sections = Observable.just([MySection(header: "基本控件", items: ["UILable的用法","UIText的用法","UIButton的用法"]),MySection(header: "高級控件", items: ["UITableView的用法","UICollectionViews的用法"])])// 創建數據源 let dataSource = RxTableViewSectionedAnimatedDataSource<MySection>(// 設置單元格configureCell: { ds, tv, ip, item inlet cell = tv.dequeueReusableCell(withIdentifier: "Cell")?? UITableViewCell(style: .default, reuseIdentifier: "Cell")cell.textLabel?.text = "\(ip.row)\(item)"return cell},// 設置分區頭標題titleForHeaderInSection: { ds, index inreturn ds.sectionModels[index].header} )self.dataSource = dataSource// 綁定單元格數據 sections.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)// 設置代理 tableView.rx.setDelegate(self).disposed(by: disposeBag)// tableView代理實現 extension MainViewController : UITableViewDelegate {// 設置單元格高度func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)-> CGFloat {guard let _ = dataSource?[indexPath],let _ = dataSource?[indexPath.section]else {return 0.0}return 60} }// 自定義Section struct MySection {var header: Stringvar items: [Item] }extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity: String {return header}init(original: MySection, items: [Item]) {self = originalself.items = items} }

② 修改分組的頭部和尾部

  • 修改代理實現,示例代碼:
// tableView代理實現 extension MainViewController : UITableViewDelegate {// 返回分區頭部視圖func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int)-> UIView? {let headerView = UIView()headerView.backgroundColor = UIColor.blacklet titleLabel = UILabel()titleLabel.text = self.dataSource?[section].headertitleLabel.textColor = UIColor.whitetitleLabel.sizeToFit()titleLabel.center = CGPoint(x: self.view.frame.width/2, y: 20)headerView.addSubview(titleLabel)return headerView}// 返回分區頭部高度func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int)-> CGFloat {return 40} }// 自定義Section struct MySection {var header: Stringvar items: [Item] }extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity: String {return header}init(original: MySection, items: [Item]) {self = originalself.items = items} }

總結

以上是生活随笔為你收集整理的RxSwift之UI控件UITableView扩展的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。