Swift学习26:UITableView

张建 lol

前言

  • UITableView 是我们开发中最常见的列表,UITableView 继承自

  • UIScrollView``UIScrollView 可以在任意方向滑动,UITableView 只能在垂直方向滑动

  • UITableView 的内容由 UITableViewCell 来显示的

  • UITableViewCell 可以使用系统自带样式,也可以自定义

创建 UITableView

  • 我们在实际开发中通常是用 延迟加载 的方式来创建,如下:
1
2
3
4
5
6
// 懒加载:延迟加载 - 第一次使用的时候才加载
lazy var tableV: UITableView = {
let tableV = UITableView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height), style: .plain)
tableV.backgroundColor = UIColor.red
return tableV
}()

注:
style 有两种样式:plaingroup
区别:
plain:
1、plain类型有多个header时,header停留(自带效果)
2、plain类型section之间没有间距
group:
1、类型有多个header时,header不停留
2、plain类型section之间有间距

  • 将其添加到指定页面上:例如 VC
1
2
// 添加tableV到vc的view上
self.view.addSubview(self.tableV)

设置代理

  • 可以设置代理
1
2
3
4
5
6
7
8
9
// 懒加载:延迟加载 - 第一次使用的时候才加载
lazy var tableV: UITableView = {
let tableV = UITableView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height), style: .plain)
tableV.backgroundColor = UIColor.red
// 设置代理
tableV.delegate = self
tableV.dataSource = self
return tableV
}()
  • 遵守代理

可以通过 extension 去遵守代理

1
2
3
extension ViewController: UITableViewDataSource,UITableViewDelegate {

}
  • 实现代理回调方法,丰富页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
extension ViewController: UITableViewDataSource,UITableViewDelegate {
// 组的个数
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
// 每组的row数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
// 每个row的cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 系统的cell
let cellId = "testCellId"
var cell = tableV.dequeueReusableCell(withIdentifier: cellId)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: cellId)
}
cell?.textLabel?.text = "标题"
cell?.detailTextLabel?.text = "内容"
cell?.imageView?.image = UIImage(named: "test")

return cell!
}
// cell的高度
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70
}
// 选中cell执行的方法
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.row)
}
}

注:系统样式的cell有三种样式:default,value1,value2,subtitle

  • default

  • value1

  • value2

  • subtitle

自定义cell

  • 创建一个 BaseTableViewCell 基类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import UIKit

class BaseTableViewCell: UITableViewCell {
// 基础
class func BaseTableViewCell(tableView:UITableView,indexPath:NSIndexPath) -> UITableViewCell{
let ID = NSStringFromClass(self);
let cls = NSClassFromString(ID) as! UITableViewCell.Type;
let cell = tableView.dequeueReusableCell(withIdentifier: ID) ?? cls.init(style: .default, reuseIdentifier: ID)
return cell
}
/*
子类默认不继承父类的初始化器,实际上是通过 重写 父类的初始化器实现的,用 override 关键字
子类调用父类的初始化区,用 super
*/
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.prepareUI()
}
// UI
func prepareUI() {
self.contentView.backgroundColor = kColorRandom();
}
// 必要初始化器:可失败
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// 反初始化器
deinit {
print("deinit")
}
}

  • 创建自定义cell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import UIKit

class CustomTableViewCell: BaseTableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.prepareUI()
}


override func prepareUI() {
super.prepareUI();
self.contentView.backgroundColor = .white;

initUI();
initConstraint();
}
func initUI() {
self.contentView.addSubview(bgV);

}
func initConstraint() {

}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

  • 修改代理回调方法给cell赋值
1
2
3
let cell = CustomTableViewCell.BaseTableViewCell(tableView: tableView, indexPath: indexPath as NSIndexPath)

return cell

cell 的插入和删除

  • 插入和删除涉及到三个代理方法 和 编辑模式的方法
1
2
// editing: 是否开启编辑状态 animated: 是否有动画效果
setEditing(_ editing:, animated:)
  • 删除的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 编辑模式:insert 添加操作、delete删除操作、none 没有任何操作
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .delete
}
// 执行编辑操作:调用此方法
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .insert {
// 添加
dataArr.insert("\(indexPath.row)", at: indexPath.row)
// 添加操作
tableView.insertRows(at: [indexPath], with: .right)
}else {
// 删除
dataArr.remove(at: indexPath.row)
// 删除
print(dataArr)
tableView.deleteRows(at: [indexPath], with: .left)
}
}
// 修改删除的文字
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "删除"
}

cell位置移动

  • 移动功能同样需要开启编辑模式
1
2
// editing: 是否开启编辑状态 animated: 是否有动画效果
setEditing(_ editing:, animated:)
  • 简单实现
1
2
3
4
5
6
7
8
9
10
// 设置cell是否可移动
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
// 移动结束后调用此方法
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let data = dataArr[sourceIndexPath.row]
dataArr.remove(at: sourceIndexPath.row)
dataArr.insert(data, at: destinationIndexPath.row)
}
  • Post title:Swift学习26:UITableView
  • Post author:张建
  • Create time:2023-03-28 08:34:36
  • Post link:https://redefine.ohevan.com/2023/03/28/Swift/Swift学习26:UITableView/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.