UITableViewCell上按鈕事件處理
阿新 • • 發佈:2019-01-07
RxSwift與UITableView的使用,之前文章簡單的實現了一下。今天主要是實現如何處理UITableViewCell上的按鈕事件。以前我們通常會選擇使用代理、閉包、通知這些方法中的一個方法,我個人喜歡閉包。但是現在已經開始使用RxSwift,所以一起來看看RxSwift中我們如何處理按鈕事件。
UITableViewCell的內部事件
一般對於cell的點選,會觸發其代理方法:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// 處理cell的點選事件
}
在Rx中,我們處理如下: tableView.rx.modelSelected(ItemModel.self)
.subscribe(onNext: { value in
print(value)
}).disposed(by: disposeBag)
或者先獲取點選的位置,然後在根據點選的位置獲取資料tableView.rx.itemSelected.asObservable() .subscribe(onNext: { index in print(index) }).disposed(by: disposeBag)
由上可知對於cell的處理還是很簡單的。
UITableViewCell上的按鈕事件
比較好的方案就是閉包,前面也談到了。那麼我們如何使用Rx來處理呢?先看一個demo
自定義cell部分
該部分內容很簡單,cell上添加了一個label和button,並進行佈局
import UIKit import SnapKit import RxSwift class CustomTableViewCell: UITableViewCell { private(set) var disposeBag = DisposeBag() lazy var info: UILabel = { let label = UILabel() label.numberOfLines = 0 label.font = UIFont.systemFont(ofSize: 20) return label }() lazy var button: UIButton = { let btn = UIButton(type: .custom) btn.setTitle("button", for: .normal) btn.setTitleColor(UIColor.black, for: .normal) btn.backgroundColor = UIColor.cyan return btn }() override func prepareForReuse() { super.prepareForReuse() disposeBag = DisposeBag() } override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupUI() setupConstraints() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupUI() { addSubview(info) addSubview(button) } private func setupConstraints() { info.snp.makeConstraints { (make) in make.left.top.right.equalToSuperview().inset(15) } button.snp.makeConstraints { (make) in make.centerX.equalToSuperview() make.top.equalTo(info.snp.bottom).offset(15) make.size.equalTo(CGSize(width: 100, height: 50)) make.bottom.equalToSuperview().offset(-15) } } }
這裡有一個關鍵的地方:prepareForReuse()方法,在方法裡面,每次重用cell的時候,我們會釋放之前的disposeBag, 然後會為cell建立一個新的disposeBag物件,這樣可以保證cell被重用的時候不會被多次訂閱,造成錯誤。
檢視控制器部分
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let titles = ["自己選擇的路,跪著也要把它走完。", "平凡的腳步也可以走完偉大的行程,世上沒有絕望的處境,只有對處境絕望的人", "世上沒有絕望的處境,只有對處境絕望的人", "第一個青春是上帝給的;第二個青春是靠自己努力的。", "每個人都會累,沒人能為你承擔所有悲傷,人總有一段時間要學會自己長大。", "每天醒來,敲醒自己的不是鐘聲,而是夢想。", "這個世界到處充滿著不公平,我們能做的不僅僅是接受,還要試著做一些反抗。"]
lazy var tableView: UITableView = {
let tv = UITableView(frame: CGRect.zero, style: .plain)
tv.dataSource = self
tv.register(CustomTableViewCell.self, forCellReuseIdentifier: "cell")
tv.estimatedRowHeight = 100
tv.rowHeight = UITableViewAutomaticDimension
return tv
}()
lazy var headView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.red
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
func setupTableView() {
view.addSubview(tableView)
tableView.snp.makeConstraints { (make) in
make.left.right.top.bottom.equalToSuperview()
}
headView.frame = CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 300)
tableView.tableHeaderView = headView
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titles.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
cell.info.text = "\(titles[indexPath.row]): \(indexPath.row)"
cell.button.rx.tap.asObservable().subscribe(onNext: {
print("\(indexPath.row)")
}).disposed(by: cell.disposeBag)
return cell
}
}
很簡單就是新增一個tableView設定相應的屬性,並訂閱點選事件。這樣就可以正確處理按鈕事件了。然後我們可以簡化一下程式碼:
class ViewController: UIViewController {
let disposeBag = DisposeBag()
let titles = ["自己選擇的路,跪著也要把它走完。", "平凡的腳步也可以走完偉大的行程,世上沒有絕望的處境,只有對處境絕望的人", "世上沒有絕望的處境,只有對處境絕望的人", "第一個青春是上帝給的;第二個青春是靠自己努力的。", "每個人都會累,沒人能為你承擔所有悲傷,人總有一段時間要學會自己長大。", "每天醒來,敲醒自己的不是鐘聲,而是夢想。", "這個世界到處充滿著不公平,我們能做的不僅僅是接受,還要試著做一些反抗。"]
lazy var tableView: UITableView = {
let tv = UITableView(frame: CGRect.zero, style: .plain)
tv.estimatedRowHeight = 100
tv.register(CustomTableViewCell.self, forCellReuseIdentifier: "cell")
tv.rowHeight = UITableViewAutomaticDimension
return tv
}()
lazy var headView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.red
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
bindTableView()
}
func setupTableView() {
view.addSubview(tableView)
tableView.snp.makeConstraints { (make) in
make.left.right.top.bottom.equalToSuperview()
}
headView.frame = CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 300)
tableView.tableHeaderView = headView
}
func bindTableView() {
Observable.of(titles)
.bind(to: tableView.rx.items(cellIdentifier: "cell", cellType: CustomTableViewCell.self)) { (indexPath, element, cell) in
cell.info.text = element
cell.button.rx.tap.asObservable().subscribe(onNext: {
print(element)
}).disposed(by: cell.disposeBag)
}.disposed(by: disposeBag)
}
}