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
- Filling a table with data
- Table View Guide