Ray Tso Ray Tso - 9 months ago 48
iOS Question

Cells temporarily disappearing when TableView beginUpdates / endUpdates

I am trying to make a expandable table view (static cells). A container view is placed inside a cell below the "Lists of options" cell, as shown below:

The problem comes with the animation when expanding / collapsing. The topmost cell of each section will disappear briefly(hidden?), then reappear after the animation ends. I have later experimented and the results are as followed:

This will not happen when using

tableView.reloadData()
.

This will happen when using
tableView.beginUpdates() / endUpdates()
pairs.

Hence I have come to the conclusion that this has sth to do with the animation. Below is my code and pictures for further explanation for said issue.

Code for hiding / showing

private func hideContainerView(targetView: UIView) {
if targetView == violationOptionsContainerView {
violationOptionContainerViewVisible = false
}
tableView.beginUpdates()
tableView.endUpdates()

UIView.animate(withDuration: 0.1, animations: { targetView.alpha = 0.0 }) { _ in
targetView.isHidden = true
}
}

private func showContainerView(targetView: UIView) {
if targetView == violationOptionsContainerView {
violationOptionContainerViewVisible = true
}
tableView.beginUpdates()
tableView.endUpdates()
targetView.alpha = 0.0
UIView.animate(withDuration: 0.1, animations: { targetView.alpha = 1.0 }) { _ in
targetView.isHidden = false
}
}


Table view

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
switch cell {
case violationTableViewCell:
if violationOptionContainerViewVisible {
hideContainerView(targetView: violationOptionsContainerView)
} else {
showContainerView(targetView: violationOptionsContainerView)
}
default: break
}
// tableView.reloadData()
// if we use this instead of begin/end updates, the cells won't disappear. But then we'll be ditching animation too.
}
tableView.deselectRow(at: indexPath, animated: true)
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 && indexPath.row == 3 {
if !violationOptionContainerViewVisible {
return 0.0
}
}
return super.tableView(tableView, heightForRowAt: indexPath)
}


Images

enter image description here

Note that the first cell in each section ("FFFF" and the "slider bar") disappears and reappears during the animation

Answer Source

After searching for a few days, I have found the cause to this behavior.

I have, for some reason, set the cells layer.zposition below default zero. This will cause the cell to be seen "below" it's background view (hence disappeared) during the animation even though it's a subview of it.

Adjusting the value back to 0 or higher will remove this issue.