使用 RXSwift 构建 UITableView

Swift Version:5.0 
RXSwift Version:5.0
复制代码

本文介绍的是如何使用 RX 构建 UITableView,需对 Swift 有基础的了解。共 1100 字,阅读需 10 min。git

先说一下构建的主要步骤,这样你们能更好的理解代码。github

使用 RXSwift 构建 UITableView 的步骤 swift

  1. 构建 Observable 类型的数据源
  2. 将数据源与 tableView 绑定
  3. 绑定 tableView 的事件(如:cell 的点击事件)
  4. 设置 tableView Delegate/DataSource 的代理方法(根据需求,非必要)

准备工做

在咱们开始以前,咱们须要在项目中集成 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 绑定。

将数据源与 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)
复制代码

在绑定方法的闭包中,咱们须要定义三个变量,三个变量分别有如下含义:

  • 第一个变量为当前cell所处的行数,即:indexPath.row
  • 第二个变量为可观察序列在当前行数索引的元素,即:texts[row]
  • 第三个变量为当前cell

闭包底层实现

绑定 tableView 的事件

经过下面代码进行绑定(cell 的点击事件):

tableView.rx.itemSelected.bind { (indexPath) in
        print(indexPath)
    }
    .disposed(by: disposeBag)
复制代码

一样,不要忘记最后的 disposed 。

到这里,咱们就完成了经过 RX 构建一个简单的 tableView 。若是你对 tableView 还有一些自定义的需求,可经过第四步骤完成。

设置 tableView Delegate/DataSource 的代理方法

经过下面的代码设置代理:

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
复制代码

总结

  • 使用 RX 可使代码简洁,易读
  • 使用 RX 语句后需调用 .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
    }
}
复制代码

参考

相关文章
相关标签/搜索