TableView 基础
本文讲讲TableView的基本使用.
顺便介绍一下delegation.
TableView用来做什么
TableView用来展示一个很长的list.
和Android中的RecyclerView不同, iOS中的TableView只能是竖直方向的list.
如何写一个最简单的TableView
一个最简单的TableViewController看起来像这样:- class ViewController: UITableViewController {
- var data: [String] = []
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do any additional setup after loading the view.
- // loadData()
- print(data)
- }
- override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- data.count
- }
- override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
- cell.textLabel?.text = data[indexPath.row]
- return cell
- }
- }
复制代码 这里data是想展示的数据类型, 可以hardcode一些数据.
这么简单是因为这个ViewController继承了UITableViewController, 并且cell的部分使用了storyboard.
这里需要用dequeueReusableCell方法, 是为了cell的复用, 因为list内容很多的时候cell view是可以循环使用的. (很像Android里的RecyclerView).
UITableViewController的签名是这样:- open class UITableViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
复制代码 它为我们做了以下三件事:
- 设置view为一个UITableView.
- 设置delegate=self.
- 设置dataSource=self.
这种方式的局限性在于第一点, 它的根view是一个TableView, 如果我们的需求比较复杂, 不仅仅是一个demo, 那么可能需要组合View.
拆解版TableView
我们也可以直接继承UIViewController类, 然后自己动手做上面的几条设置.
Delegate & DataSource
TableView有两个重要的方面需要关注:
- UITableViewDelegate: 管理和用户的交互, 比如选择, 滑动手势等. 没有必须要实现的方法.
- UITableViewDataSource: 提供和管理数据, 包括了数据对应的cell或者header. 有两个必须要实现的方法(如上面的代码例子所示).
继承UIViewController
继承UIViewController而不是UITableViewController之后, 需要自己写一个tableView并加在view里.
再分别实现UITableViewDelegate和UITableViewDataSource, 这里写在extension里, 拆分完之后set给tableView:- tableView.delegate = self
- tableView.dataSource = self
复制代码 整体改造后代码如下:- class ViewController: UIViewController {
- var data: [String] = ["Hello", "World"]
- private let tableView = UITableView()
- override func loadView() {
- view = UIView()
- view.addSubview(tableView)
- tableView.translatesAutoresizingMaskIntoConstraints = false
- NSLayoutConstraint.activate([
- tableView.topAnchor.constraint(equalTo: view.topAnchor),
- tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
- tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
- tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
- ])
- }
- override func viewDidLoad() {
- super.viewDidLoad()
- tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
- tableView.delegate = self
- tableView.dataSource = self
- }
- }
- extension ViewController: UITableViewDelegate {}
- extension ViewController: UITableViewDataSource {
- func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
- data.count
- }
- func tableView(_: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as? MyCell {
- cell.configure(with: data[indexPath.row])
- return cell
- }
- return UITableViewCell()
- }
- }
复制代码 自己的Cell class
这里Cell也改用代码类, 写一个这样的类:- class MyCell: UITableViewCell {
- private let label = UILabel()
- override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
- super.init(style: style, reuseIdentifier: reuseIdentifier)
- contentView.addSubview(label)
- label.translatesAutoresizingMaskIntoConstraints = false
- NSLayoutConstraint.activate([
- label.topAnchor.constraint(equalTo: contentView.topAnchor),
- label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
- label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
- label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
- ])
- }
- @available(*, unavailable)
- required init?(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- func configure(with data: String) {
- label.text = data
- }
- }
复制代码 注意tableView注册这个Cell类型:- override func viewDidLoad() {
- super.viewDidLoad()
- tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
- }
复制代码 补充知识: Delegation
上面的方法初看可能会非常怪. 这里还涉及到了一个知识点是iOS中的delegate.
它存在的意义是为了拓展本身类的功能.
Apple自己的很多API就用了delegate protocol, 比如UIApplicationDelegate, UITableViewDelegate.
如果我们想自己定义一个:- protocol MyTypeDelegate: AnyObject {
- func myType(_ myType: MyType,
- shouldDoSomething argumentString: String) -> Bool
- func myType(_ myType: MyType,
- didAbortWithError error: Error)
- func myTypeDidFinish(_ myType: MyType)
- }
- class MyType {
- weak var delegate: MyTypeDelegate?
- }
复制代码 定义delegation的几个原则:
- 方法名以被代理的类型开头.
- 方法的第一个参数是被代理的对象.
References
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |