Swift - 实现tableView静态单元格与动态单元格混合使用(附样例)
作者:hangge | 2016-10-20 09:14
使用表格(UITableView)时,我们可以选择其采用静态单元格(Static Cell)还是动态单元格(Dynamic Cell)。前者使用方便,只需要在 storyboard 中设置好各个单元格即可。后者使用灵活,可以根据绑定的数据动态创建对应的单元格并显示。
但这二者并不是互斥的,我们可以在同一个 tableView 混合使用它们。比如部分单元格使用动态的,部分单元格使用静态的。下面通过一个样例作为演示。1,样例效果图
(1)下面是一 wifi 选择页面。单元格一共分为三个 section。
(2)第1个、第3个 section 里的单元格都是固定的,所以我们可以使用 Static Cell。
(3)中间 section 里的单元格是根据 wifi 列表数据来动态显示的,所以使用 Dynamic Cell。
(1)在 Main.storyboard 中添加一个 table view controller。作为演示,这里勾选“Is Initial View Controller”将其作为初始页面。

(2)将 table view 的 Content 改成 Static Cells,Sections 改成 3。

(3)由于第1个、第3个的分组里的 cell 都是不变的。所以我们这里直接配置好它们内部的组件。

(4)而第2个分组里的单元格是动态的,这里就将其 Rows 设为1。


(5)创建一个自定义类 TableViewController(继承自 UITableViewController)。将场景中的 TableViewController 与新建这个新建类进行绑定。

(6)TableViewController.swift 代码如下:
import UIKit
class TableViewController: UITableViewController {
//wifi数据集合
let wifiArray = ["hangge-wifi-1","hangge-wifi-2","hangge-wifi-3"]
override func viewDidLoad() {
super.viewDidLoad()
//创建一个重用的单元格
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "wifiCell")
//去除尾部多余的空行
self.tableView.tableFooterView = UIView(frame:CGRect.zero)
//设置分区头部字体颜色和大小
UILabel.appearance(whenContainedInInstancesOf: [UITableViewHeaderFooterView.self])
.textColor = UIColor.gray
UILabel.appearance(whenContainedInInstancesOf: [UITableViewHeaderFooterView.self])
.font = UIFont.systemFont(ofSize: 13.0, weight: UIFontWeightMedium)
}
//返回分区数
override func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
//返回每个分区中单元格的数量
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
-> Int {
if section == 1 {
return wifiArray.count
}else{
return 1
}
}
//设置cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
//只有第二个分区是动态的,其它默认
if indexPath.section == 1 {
//用重用的方式获取标识为wifiCell的cell
let cell = tableView.dequeueReusableCell(withIdentifier: "wifiCell",
for: indexPath)
cell.textLabel?.text = wifiArray[indexPath.row]
return cell
}else{
return super.tableView(tableView, cellForRowAt: indexPath)
}
}
//因为第二个分区单元格动态添加,会引起cell高度的变化,所以要重新设置
override func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 1{
return 44
}else{
return super.tableView(tableView, heightForRowAt: indexPath)
}
}
//当覆盖了静态的cell数据源方法时需要提供一个代理方法。
//因为数据源对新加进来的cell一无所知,所以要使用这个代理方法
override func tableView(_ tableView: UITableView,
indentationLevelForRowAt indexPath: IndexPath) -> Int {
if indexPath.section == 1{
//当执行到日期选择器所在的indexPath就创建一个indexPath然后强插
let newIndexPath = IndexPath(row: 0, section: indexPath.section)
return super.tableView(tableView, indentationLevelForRowAt: newIndexPath)
}else{
return super.tableView(tableView, indentationLevelForRowAt: indexPath)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
源码下载:关于动态添加、移除单元格,还可以参考我的另一篇文章:Swift - 动态添加删除TableView的单元格(以及内部元件)
全部评论(3)
站长,请问中间那个动态单元格能自定义多行显示吗? 毕竟不同情况要求不一样。
站长回复:可以的,只要把单元格label的numberOfLines设置成你想显示的行数就可以了。
站长,为什么设置cell里面的indexPath.row有些程序运行运行没问题 有些程序报错
Thread1:Fatal error: Unexpectedly found nil while unwrapping an optional value
这个错的,求解!!!
站长回复:不太明白你的意思,是我样例又问题吗?
你的是 self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "wifiCell") 。 能不能直接用界面上的那个单元格。 我用了好像一直报错
站长回复:确实不可以,如果把将table view的Content设为Static Cells的话就不行了。