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里.

再分别实现UITableViewDelegateUITableViewDataSource, 这里写在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

[Android开发学iOS系列] TableView展现一个list的更多相关文章

  1. [Android开发学iOS系列] 工具篇: Xcode使用和快捷键

    [Android开发学iOS系列] 工具篇: Xcode使用和快捷键 工欲善其事必先利其器. 编辑 Cmd + N: 新建文件 Option + Cmd + N: 新建文件夹 Cmd + / : 注释 ...

  2. [Android开发学iOS系列] iOS写UI的几种方式

    [Android开发学iOS系列] iOS写UI的几种方式 作为一个现代化的平台, iOS的发展也经历了好几个时代. 本文讲讲iOS写UI的几种主要方式和各自的特点. iOS写UI的方式 在iOS中写 ...

  3. [Android开发学iOS系列] Auto Layout

    [Android开发学iOS系列] Auto Layout 内容: 介绍什么是Auto Layout. 基本使用方法 在代码中写约束的方法 Auto Layout的原理 尺寸和优先级 Auto Lay ...

  4. [Android开发学iOS系列] 语言篇: Swift vs Kotlin

    Swift vs Kotlin 这篇文章是想着帮助Android开发快速学习Swift编程语言用的. (因为这个文章的作者立场就是这样.) 我不想写一个非常长, 非常详尽的文章, 只是想写一个快速的版 ...

  5. [Android开发学iOS系列] ViewController

    iOS ViewController 写UIKit的代码, ViewController是离不开的. 本文试图讲讲它的基本知识, 不是很深入且有点杂乱, 供初级选手和跨技术栈同学参考. What is ...

  6. [Android开发学iOS系列] 快速上手UIKit

    快速上手iOS UIKit UIKit是苹果官方的framework, 其中包含了各种UI组件, window和view, 事件处理, 交互, 动画, 资源管理等基础设施支持. 按照前面的介绍, 用U ...

  7. Android开发—智能家居系列】(二):用手机对WIFI模块进行配置

    在实际开发中,我开发的这款APP是用来连接温控器,并对温控器进行控制的.有图为证,哈哈. 上一篇文章[Android开发—智能家居系列](一):智能家居原理的文末总结中写到: 手机APP控制智能温控器 ...

  8. android开发学习笔记系列(2)-android应用界面编程

    前言 本篇博客将会简要介绍andriod开发过程中的一些界面元素和编程的实现,我将大家走进安卓的XML世界,当然可能会涉及到java代码,当然本文主要是介绍XML文件的界面布局. 那么我们的XML存在 ...

  9. android开发学习笔记系列(1)-android起航

    前言 在学习安卓的过程中,我觉得非常有必要将自己所学的东西进行整理,因为每每当我知道我应该是如何去实现功能的时候,有许多细节问题我总是会遗漏,因此我也萌生了写一系列博客来描述自己学习的路线,让我的an ...

  10. android开发学习笔记系列(4)--android动态布局

    前言 在做一个有关苏果APP的项目中,但是fuck的是,我完全使用相对布局之后及线性布局之后发现坑爹的事情了,屏幕不能适配,这是多大的痛,意味着,必须使用相应的代码实现动态布局!呵呵,不做项目不知道, ...

随机推荐

  1. ProxySQL Cluster 高可用集群 + MySQL MGR环境部署 (多写模式) 部署记录

    文章转载自:https://blog.51cto.com/u_6215974/4937192 ProxySQL 在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数 ...

  2. 通过Metricbeat实现外部对Elastic Stack的监控

    对于Elastic Stack监视的所有用户,建议使用外部数据收集. 概括一下: 关闭Elastic Stack自带的监控功能,然后使用metricbeat收集Elastic Stack数据传输到另外 ...

  3. k8s上安装elasticsearch集群

    官方文档地址:https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-quickstart.html yaml文件地址:https://dow ...

  4. 安装 Ubuntu 教程

    1.选择中文安装 2.****到了如下界面,我们点击继续: 3.然后点击,现在安装: 4.****到了这界面,点击继续: 5.如下,输入你的位置,随便输入就好: 6.****然后选择汉语,点击继续: ...

  5. 我的Vue之旅、05 导航栏、登录、注册 (Mobile)

    第一期 · 使用 Vue 3.1 + TypeScript + Router + Tailwind.css 构建手机底部导航栏.仿B站的登录.注册页面. 代码仓库 alicepolice/Vue-05 ...

  6. Linux shell猜数游戏

    题目:猜随机数随机1-100中的一个数字,要求用户猜数字,猜中则退出脚本并告知用户猜测次 数和随机数字,否则要求用户继续猜,并告知当前猜的数字和随机数的关系. #!/bin/bash #猜数游戏 Ra ...

  7. PyCharm安装PyQt5及其工具(Qt Designer、PyUIC、PyRcc)详细教程

    摘要:Qt是常用的用户界面设计工具,而在Python中则使用PyQt这一工具包,它是Python编程语言和Qt库的成功融合.这篇博文通过图文详细介绍在PyCharm中如何完整优雅地安装配置PyQt5的 ...

  8. HDU1423 Greatest Common Increasing Subsequence (DP优化)

    LIS和LCS的结合. 容易写出方程,复杂度是nm2,但我们可以去掉一层没有必要的枚举,用一个变量val记录前一阶段的最优解,这样优化成nm. 1<=k<j,j增加1,k的上界也增加1,就 ...

  9. this硬绑定

    一.this显示绑定 this显示绑定,顾名思义,它有别于this的隐式绑定,而隐式绑定必须要求一个对象内部包含一个指向某个函数的属性(或者某个对象或者上下文包含一个函数调用位置),并通过这个属性间接 ...

  10. VS中git概念解析与深度使用

    基础概念 四个区 工作区(Working Area) 暂存区(Stage) 本地仓库(Local Repository) 远程仓库(Remote Repository) 五种状态 未修改(Origin ...