直接上现象:
可以看到在调用reloadSections
方法更新Section 2
时,由于Section 1
只有一个Header
区域,没有对应的Cell
, 从而引起了这个现象。更新调用的方法如下:
func reloadSection2(_ sender: UIButton) {
tableView.reloadSections(IndexSet.init(integer: 2), with: .automatic)
}
问题说明
按照通常的逻辑关系,没有行数的Section
压根就不应该创建相关的UI,但在实际应用时,由于数据获取和UI显示的不同步或者某些历史原因,导致我们先给UI占了位,等数据获取后再刷新显示,这就出现了上面所说的场景和现象了。
如果情况只是这样,那还好搞。但事实是,有时候你还在Section
没有内容的时候把那个Section Header
给隐藏起来了,这就给定位问题带来了很大的麻烦。我和我的小伙伴花了整整一天,才在项目中找到原因,简直累死。现在做了Demo来演示这个问题。
解决方案1 - 取消动画的方式
- 全局刷新
TableView
:
func reloadSection2(_ sender: UIButton) {
tableView.reloadData()
}
效果:
- 强制取消
reloadSections
的动画效果:
func reloadSection2(_ sender: UIButton) {
UIView.performWithoutAnimation {
tableView.reloadSections(IndexSet.init(integer: 2), with: .automatic)
}
}
效果:
可是如果我们非要保留这个过渡动画呢?
你没有看错,需求有时就是这个样子的,所以才会发生流血事件 -_-#
解决方案2 - 保留动画效果
- 给空Section指定一个行,并通过设置高度控制显示/隐藏
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return 1 //强制给Section 1指定一行Cell
}
return 3
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 1 {
return 0 //通过控制Section 1的Cell的高度来隐藏这个指定的Cell
}
return 40
}
效果:
如果你把动画放慢,会发现在动画过程中,Section 1
强制指定的的Cell有时会在动画初期出现,这个是由于View
的clipsToBounds
没有设置的缘故,导致视图的内容可以在边界外显示出来。我们可以给Cell
设置这个属性,以消除这个影响:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = self.randomSmallCaseString(length: 20);
cell.backgroundColor = UIColor.green
cell.clipsToBounds = true; // 设置这个属性,那内容限制在视图的边框内部不会越界显示
return cell
}
这种方法不官方,但确实可行,是目前我想到的保留动画的解决方式。如果你们有其它的解决方式,请一定通知我: <824219521@qq.com>