Swift Version:5.0
RXSwift Version:5.0
複製代碼
本文介紹的是如何使用 RX 構建 UITableView,需對 Swift 有基礎的瞭解。共 1100 字,閱讀需 10 min。git
先說一下構建的主要步驟,這樣你們能更好的理解代碼。github
使用 RXSwift 構建 UITableView 的步驟 swift
Observable
類型的數據源在咱們開始以前,咱們須要在項目中集成 RXSwift,具體步驟可參見 RXSwift。成功集成以後,咱們須要在要使用 RXSwift 的文件中導入它:bash
import RxSwift
複製代碼
接着,咱們要建立一個 DisposeBag
類型的全局變量(必定要是全局變量
):閉包
let disposeBag = DisposeBag()
複製代碼
關於 DisposeBag 的做用: DisposeBag 對於 RX 至關於 ARC 對於 iOS,即它是 RX 管理對象內存的一種方式。
異步
最後,將須要使用的 cell 進行註冊:async
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
複製代碼
OK,到如今爲止,咱們已經完成了全部的準備工做。接下來,咱們能夠根據上面的步驟來構建 tableView 了。ide
Observable
類型的數據源首先,咱們須要構建 Observable
類型的數據源。至於爲何要構建 Observable
類型的數據,咱們能夠從 RXSwift 的文檔上一探究竟。ui
它的文檔上是這麼寫的:Every Observable sequence is just a sequence. The key advantage for an Observable vs Swift's Sequence is that it can also receive elements asynchronously
。這句話的意思是說,可觀察序列和 Swift 的原生序列本質上是同樣的,但它們有一個最主要的不一樣,那就是可觀察序列能夠異步接受元素
。spa
經過下面的代碼建立 Observable
類型的數據源:
let texts = ["Objective-C", "Swift", "RXSwift"]
let textsObservable = Observable.from(optional: texts)
複製代碼
此時,你用 option 鍵查看 textsObservable 屬性的類型,應該顯示的是 Observable<String>
。
可供使用的數據源已經構建完成,接下來須要將數據源與 tableView 綁定。
經過下面代碼進行綁定(不要忘記最後的 .disposed(by: disposeBag)
):
textsObservable.bind(to: tableView.rx
.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (row, text, cell) in
cell.textLabel?.text = text
}
.disposed(by: disposeBag)
複製代碼
在綁定方法的閉包中,咱們須要定義三個變量,三個變量分別有如下含義:
indexPath.row
texts[row]
經過下面代碼進行綁定(cell 的點擊事件):
tableView.rx.itemSelected.bind { (indexPath) in
print(indexPath)
}
.disposed(by: disposeBag)
複製代碼
一樣,不要忘記最後的 disposed 。
到這裏,咱們就完成了經過 RX 構建一個簡單的 tableView 。若是你對 tableView 還有一些自定義的需求,可經過第四步驟完成。
經過下面的代碼設置代理:
tableView.rx.setDelegate(self).disposed(by: disposeBag)
tableView.rx.setDataSource(self).disposed(by: disposeBag)
複製代碼
而後,你就能夠實現相關的代理方法來進行自定義了,以設置高度舉例:
extension ALGExploreDetailVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
複製代碼
注意:若是你不須要使用 UITableViewDelegate/UITableViewDataSource 的委託方法的話,你是能夠不寫的。
// 不使用 RX 的話,須要實現代理方法
tableView.delegate = self
tableView.dataSource = self
extension ViewController: UITableViewDelegate, UITableViewDataSource {
....
}
// 使用 RX
// 綁定便可,不需寫上面的代碼
textsObservable.bind(to: tableView.rx
.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (row, text, cell) in
cell.textLabel?.text = "\(text)"
}
.disposed(by: disposeBag)
複製代碼
若是使用 RX 綁定了 tableView ,再使用下面的代碼就不對了,咱們需使用 RX 設置代理的方法。
tableView.delegate = self
複製代碼
.disposed(by: disposeBag)
,釋放內存import UIKit
import RxSwift
class TestViewController: UIViewController {
var tableView = UITableView(frame: .zero)
let kCellHeight: CGFloat = 40
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
setupSubviews()
}
}
extension TestViewController {
func setupSubviews() {
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.safeEdges(to: view)
//1.建立可觀察數據源
let texts = ["Objective-C", "Swift", "RXSwift"]
let textsObservable = Observable.from(optional: texts)
//2. 將數據源與 tableView 綁定
textsObservable.bind(to: tableView.rx
.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (row, text, cell) in
cell.textLabel?.text = text
}
.disposed(by: disposeBag)
//3. 綁定 tableView 的事件
tableView.rx.itemSelected.bind { (indexPath) in
print(indexPath)
}
.disposed(by: disposeBag)
//4. 設置 tableView Delegate/DataSource 的代理方法
tableView.rx.setDelegate(self).disposed(by: disposeBag)
}
}
extension TestViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
複製代碼