生活随笔
收集整理的這篇文章主要介紹了
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(["文本輸入框的用法","開關按鈕的用法","進度條的用法","文本標簽的用法",])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 的數據源做了一層包裝,使用它可以大大減少我們的工作量。
① 安裝配置
pod
'RxDataSources', '~> 3.0'
github
"RxSwiftCommunity/RxDataSources" ~> 3.0
- 手動安裝:
-
- 在 RxDataSources 上將 RxDataSources 下載到本地,并引入到項目中來:
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())
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())
struct MySection {var header
: Stringvar items
: [Item]
}extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity
: String {return header
}init(original
: MySection, items
: [Item]) {self = original
self.items
= items
}
}
③ 多分區的 UITableView
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
}
items
.bind(to
: tableView
.rx
.items(dataSource
: dataSource
)).disposed(by
: 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
}
struct MySection {var header
: Stringvar items
: [Item]
}extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity
: String {return header
}init(original
: MySection, items
: [Item]) {self = original
self.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
) .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
.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 個操作命令的具體實現:
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
= 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
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)
}
struct MySection {var header
: Stringvar items
: [SectionItem]
}extension MySection : SectionModelType {typealias Item = SectionIteminit(original
: MySection, items
: [Item]) {self = original
self.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
)
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}
}
struct MySection {var header
: Stringvar items
: [Item]
}extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity
: String {return header
}init(original
: MySection, items
: [Item]) {self = original
self.items
= items
}
}
② 修改分組的頭部和尾部
extension MainViewController : UITableViewDelegate {func tableView(_ tableView
: UITableView, viewForHeaderInSection section
: Int)-> UIView? {let headerView
= UIView()headerView
.backgroundColor
= UIColor.black
let 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}
}
struct MySection {var header
: Stringvar items
: [Item]
}extension MySection : AnimatableSectionModelType {typealias Item = Stringvar identity
: String {return header
}init(original
: MySection, items
: [Item]) {self = original
self.items
= items
}
}
總結
以上是生活随笔為你收集整理的RxSwift之UI控件UITableView扩展的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。