Some odd behaviour. Got a UITableview with dynamic custom cell. As part of the custom cell is a UIStackView which contains a dynamic number of buttons. These display as expected. See image 1
However, if the tableview is quite long (lots of rows), then on scrolling it seems to start overlaping cell contents, but only at the top of the UIStackView. More I scroll, the more layers are added. See image 2

I've emptied the UIStackView at the start of each cell creation (this topped the buttons immediately duplicating but not stopped this layering duplication on scrolling), and also tried calling prepare for resume in the customer cell. Code below.
I can't seem to work out why upon scrolling a duplication is occurring at the first row (nowhere else). And the more I scroll the more duplication occurs.
Any help appreciated
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// gets input type (button or numerical input - selected cellView type to use
let inputCellType = formArray[indexPath.row][3]
if (inputCellType == "button"){
guard let cell = tableView.dequeueReusableCell(withIdentifier: FormVerticalCell.reuseIdentifier, for: indexPath) as? FormVerticalCell else {
fatalError("Unexpected Index Path")
}
for arrangedSubview in cell.buttonStack.arrangedSubviews {
cell.buttonStack.removeArrangedSubview(arrangedSubview)
}
// Cell question label
cell.questionLabel.textColor = .black
cell.questionLabel.text = formArray[indexPath.row][0]
cell.buttonStack.spacing = 5.0
cell.buttonStack.axis = .vertical
cell.buttonStack.alignment = .fill
cell.buttonStack.distribution = .fill
cell.buttonStack.translatesAutoresizingMaskIntoConstraints = false
let centerStyle = NSMutableParagraphStyle()
centerStyle.alignment = NSTextAlignment.center
var ac = AttributeContainer()
ac.font = UIFont(name: "Ariel", size: 16)
ac.paragraphStyle = centerStyle
let tempOptions = formArray[indexPath.row][1]
let optionsArray = tempOptions.components(separatedBy: ",")
var btnArray = [UIButton]()
for i in 0..<optionsArray.count {
var cfg = UIButton.Configuration.filled()
cfg.attributedTitle = AttributedString(optionsArray[i], attributes: ac)
cfg.baseBackgroundColor = UIColor(red:0.8, green:0.6, blue:0.0, alpha:0.1)
cfg.baseForegroundColor = .black
let handler: UIButton.ConfigurationUpdateHandler = { button in
switch button.state {
case [.selected, .highlighted]:
button.configuration?.baseBackgroundColor = UIColor(red:0.8, green:0.6, blue:0.0, alpha:1.0)
button.configuration?.baseForegroundColor = .white
case .selected:
button.configuration?.baseBackgroundColor = UIColor(red:0.8, green:0.6, blue:0.0, alpha:1.0)
button.configuration?.baseForegroundColor = .white
case .highlighted:
button.configuration?.baseBackgroundColor = UIColor(red:0.8, green:0.6, blue:0.0, alpha:1.0)
button.configuration?.baseForegroundColor = .white
default:
button.configuration?.baseBackgroundColor = UIColor(red:0.8, green:0.6, blue:0.0, alpha:0.1)
button.configuration?.baseForegroundColor = .black
}
}
let button = UIButton(configuration: cfg)
button.configurationUpdateHandler = handler
button.tag = i
let tempOptionsScores = formArray[indexPath.row][2]
btnArray.append(button)
cell.buttonStack.addArrangedSubview(btnArray.last!)
button.addAction { [self] in
button.isSelected = true
let optionsScoresArray = tempOptionsScores.components(separatedBy: ",")
let tempScore = optionsScoresArray[button.tag]
scoreArrayDouble[indexPath.row] = Double(tempScore)!
updateScore()
for i in 0..<btnArray.count
{
if (i != button.tag) {
btnArray[i].isSelected = false
}
}
}
}
cell.layoutIfNeeded()
return cell
}
import UIKit
class FormVerticalCell: UITableViewCell {
static let reuseIdentifier = "vertical"
@IBOutlet var buttonView: UIView!
@IBOutlet weak var buttonStack: UIStackView!
@IBOutlet var questionLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func prepareForReuse() {
super.prepareForReuse()
for arrangedSubview in buttonStack.arrangedSubviews {
buttonStack.removeArrangedSubview(arrangedSubview)
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
EDIT: It seems the UIButtons in the stack view are overlapping on each row after that row has scrolled off page. Basically duplicates created, but all on one point. Removing:
for arrangedSubview in buttonStack.arrangedSubviews {
buttonStack.removeArrangedSubview(arrangedSubview)
}
Resolves the overlapping...but still have duplicates that now extend downwards.
Overall, I need to remove the UIStackView contents due to reuse, but but using above code (removeArrangedsubview, just seems to collapse upon itself, causing the overlap.
Any ideas?
