前面我們講了最基礎的RxSwift知識點。
本來應該繼續講知識點。但是為了大家學的不那麼枯燥,我們現在開始講平時開發經常用到的一些控件。在期間穿插一些知識點。
今天我們將的是 iOS開發中最常用的UITableview控件。
一、基本用法
先上代碼:
import UIKit
import RxSwift
import RxCocoa
class 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([
"UILable的用法",
"UIText的用法",
"UIButton的用法"
])
//設置單元格數據(其實就是對 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)
}
}
cell選中事件
//獲取選中項的索引
tableView.rx.itemSelected.subscribe(onNext: { indexPath in
print("選中項的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
//獲取選中項的內容
tableView.rx.modelSelected(String.self).subscribe(onNext: { item in
print("選中項的標題為:\(item)")
}).disposed(by: disposeBag)
如果需要再block裡調用self方法,在 in 前面的 變量前加上 [weak self] :
tableView.rx.itemSelected.subscribe(onNext: { [weak self] indexPath in
self?.showMessage("選中項的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
cell取消選中事件
//獲取被取消選中項的索引
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)
cell將要顯示出來的事件
//獲取選中項的索引
tableView.rx.willDisplayCell.subscribe(onNext: { cell, indexPath in
print("將要顯示單元格indexPath為:\(indexPath)")
print("將要顯示單元格cell為:\(cell)\n")
}).disposed(by: disposeBag)
RxDataSources
RxDataSource 的本質就是使用 RxSwift 對 UITableView 和 UICollectionView 的數據源做了一層包裝。使用它可以大大減少我們的工作量。
如果我們的 tableview 需要顯示多個 section、或者更加複雜的編輯功能時,可以藉助 RxDataSource 這個第三方庫幫我們完成。
引入項目:
CocoaPods:
pod 'RxDataSources', '~> 3.0'
Carthage:
github "RxSwiftCommunity/RxDataSources" ~> 3.0
RxDataSources 是以 section 來做為數據結構的。所以不管我們的 tableView是單分區還是多分區,在使用 RxDataSources 的過程中,都需要返回一個 section 的數組。
我們要顯示下面的內容:
單分區的 TableView
一:使用自帶的Section
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class 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([
SectionModel(model: "", items: [
"UILable的用法",
"UIText的用法",
"UIButton的用法"
])
])
//創建數據源
let dataSource = RxTableViewSectionedReloadDataSource
<sectionmodel>>(configureCell: {
(dataSource, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(indexPath.row):\(element)"
return cell
})
//綁定單元格數據
items.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
}
/<sectionmodel>
二:使用自定義的Section
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class 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 sections = Observable.just([
MySection(header: "", items: [
"UILable的用法",
"UIText的用法",
"UIButton的用法"
])
])
//創建數據源
let dataSource = RxTableViewSectionedAnimatedDataSource<mysection>(
//設置單元格
configureCell: { ds, tv, ip, item in
let 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: String
var items: [Item]
}
extension MySection : AnimatableSectionModelType {
typealias Item = String
var identity: String {
return header
}
init(original: MySection, items: [Item]) {
self = original
self.items = items
}
}
/<mysection>
多分區的UITableView
一:使用自帶的Section
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class 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([
SectionModel(model: "基本控件", items: [
"UILable的用法",
"UIText的用法",
"UIButton的用法"
]),
SectionModel(model: "高級控件", items: [
"UITableView的用法",
"UICollectionViews的用法"
])
])
//創建數據源
let dataSource = RxTableViewSectionedReloadDataSource
<sectionmodel>>(configureCell: {
(dataSource, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(indexPath.row):\(element)"
return cell
})
//設置分區頭標題
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)
}
}
/<sectionmodel>
二:使用自定義的Section
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class 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 sections = Observable.just([
MySection(header: "基本控件", items: [
"UILable的用法",
"UIText的用法",
"UIButton的用法"
]),
MySection(header: "高級控件", items: [
"UITableView的用法",
"UICollectionViews的用法"
])
])
//創建數據源
let dataSource = RxTableViewSectionedAnimatedDataSource<mysection>(
//設置單元格
configureCell: { ds, tv, ip, item in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")
?? UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = "\(ip.row):\(item)"
return cell
},
//設置分區頭標題
titleForHeaderInSection: { ds, index in
return ds.sectionModels[index].header
}
)
//綁定單元格數據
sections
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
}
//自定義Section
struct MySection {
var header: String
var items: [Item]
}
extension MySection : AnimatableSectionModelType {
typealias Item = String
var identity: String {
return header
}
init(original: MySection, items: [Item]) {
self = original
self.items = items
}
}
/<mysection>
閱讀更多 雲端夢想科技 的文章