[Android开发学iOS系列] TableView展现一个list

金歌  金牌会员 | 2022-11-22 13:58:23 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 818|帖子 818|积分 2454

TableView 基础

本文讲讲TableView的基本使用.
顺便介绍一下delegation.
TableView用来做什么

TableView用来展示一个很长的list.
和Android中的RecyclerView不同, iOS中的TableView只能是竖直方向的list.
如何写一个最简单的TableView

一个最简单的TableViewController看起来像这样:
  1. class ViewController: UITableViewController {
  2.     var data: [String] = []
  3.     override func viewDidLoad() {
  4.         super.viewDidLoad()
  5.         // Do any additional setup after loading the view.
  6.         // loadData()
  7.         print(data)
  8.     }
  9.     override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  10.         data.count
  11.     }
  12.     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  13.         let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
  14.         cell.textLabel?.text = data[indexPath.row]
  15.         return cell
  16.     }
  17. }
复制代码
这里data是想展示的数据类型, 可以hardcode一些数据.
这么简单是因为这个ViewController继承了UITableViewController, 并且cell的部分使用了storyboard.
这里需要用dequeueReusableCell方法, 是为了cell的复用, 因为list内容很多的时候cell view是可以循环使用的. (很像Android里的RecyclerView).
UITableViewController的签名是这样:
  1. 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:
  1. tableView.delegate = self
  2. tableView.dataSource = self
复制代码
整体改造后代码如下:
  1. class ViewController: UIViewController {
  2.     var data: [String] = ["Hello", "World"]
  3.     private let tableView = UITableView()
  4.     override func loadView() {
  5.         view = UIView()
  6.         view.addSubview(tableView)
  7.         tableView.translatesAutoresizingMaskIntoConstraints = false
  8.         NSLayoutConstraint.activate([
  9.             tableView.topAnchor.constraint(equalTo: view.topAnchor),
  10.             tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
  11.             tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
  12.             tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
  13.         ])
  14.     }
  15.     override func viewDidLoad() {
  16.         super.viewDidLoad()
  17.         tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
  18.         tableView.delegate = self
  19.         tableView.dataSource = self
  20.     }
  21. }
  22. extension ViewController: UITableViewDelegate {}
  23. extension ViewController: UITableViewDataSource {
  24.     func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
  25.         data.count
  26.     }
  27.     func tableView(_: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  28.         if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as? MyCell {
  29.             cell.configure(with: data[indexPath.row])
  30.             return cell
  31.         }
  32.         return UITableViewCell()
  33.     }
  34. }
复制代码
自己的Cell class

这里Cell也改用代码类, 写一个这样的类:
  1. class MyCell: UITableViewCell {
  2.     private let label = UILabel()
  3.     override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  4.         super.init(style: style, reuseIdentifier: reuseIdentifier)
  5.         contentView.addSubview(label)
  6.         label.translatesAutoresizingMaskIntoConstraints = false
  7.         NSLayoutConstraint.activate([
  8.             label.topAnchor.constraint(equalTo: contentView.topAnchor),
  9.             label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
  10.             label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
  11.             label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
  12.         ])
  13.     }
  14.     @available(*, unavailable)
  15.     required init?(coder _: NSCoder) {
  16.         fatalError("init(coder:) has not been implemented")
  17.     }
  18.     func configure(with data: String) {
  19.         label.text = data
  20.     }
  21. }
复制代码
注意tableView注册这个Cell类型:
  1. override func viewDidLoad() {
  2.         super.viewDidLoad()
  3.         tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
  4. }
复制代码
补充知识: Delegation

上面的方法初看可能会非常怪. 这里还涉及到了一个知识点是iOS中的delegate.
它存在的意义是为了拓展本身类的功能.
Apple自己的很多API就用了delegate protocol, 比如UIApplicationDelegate, UITableViewDelegate.
如果我们想自己定义一个:
  1. protocol MyTypeDelegate: AnyObject {
  2.     func myType(_ myType: MyType,
  3.                       shouldDoSomething argumentString: String) -> Bool
  4.     func myType(_ myType: MyType,
  5.                       didAbortWithError error: Error)
  6.     func myTypeDidFinish(_ myType: MyType)
  7. }
  8. class MyType {
  9.     weak var delegate: MyTypeDelegate?
  10. }
复制代码
定义delegation的几个原则:

  • 方法名以被代理的类型开头.
  • 方法的第一个参数是被代理的对象.
References


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金歌

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表