Dequeuereuseable cells plus UIStackViews

soooo. I’ve been beating my head against this one for hours. as soon as I scroll the tableView the cells start making gibberish, which I know is because it isn’t refreshing the cell before applying the new data. But for the life of me I can’t figure out how to remove the previous data from the cells when the data is comprised of several stack views with a model disbursed as strings into all the labels of each view. this is the craziness of the customTableViewCell file. the main ViewController is really just a basic tableView. I’m trying to display the model and data at the bottom in a tableView

EDIT: I found view.removeFromSuperview() but it still doesn’t seem to work? it looks like it removes the stacks but leaves the data that was in those stacks in the cell. I decided to add the ViewController code cause it does seem to be relevant

class ViewController: UIViewController {

let VCInstanceOfScaleData = ScaleData()
var theArrayForVC2: [ScaleModel] = []

let scaleTableView: UITableView = {
    let table = UITableView()
    table.register(CustomTableViewCell.self, forCellReuseIdentifier: "cell")
    table.rowHeight = 144
    table.allowsSelection = false
    return table
}()

override func viewDidLoad() {
    super.viewDidLoad()
    
    scaleTableView.delegate = self
    scaleTableView.dataSource = self
    
    view.addSubview(scaleTableView)
    scaleTableView.frame = view.bounds
    scaleTableView.backgroundColor = .black
    
    theArrayForVC2 = VCInstanceOfScaleData.createArray()
}
}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) → Int {
return theArrayForVC2.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
    cell.fullStackSetup(tableIndex: indexPath.row)
    return cell
}

}

class CustomTableViewCell: UITableViewCell {

let cellScaleData = ScaleData()
var mainStack: UIStackView = {
    let stack = UIStackView()
    stack.axis = .vertical
    stack.distribution = .fillEqually
    stack.spacing = 1
    stack.alignment = .center
    stack.translatesAutoresizingMaskIntoConstraints = false
    stack.autoresizesSubviews = true
    
    return stack
}()

func fullStackSetup(tableIndex:Int) {

    
    
    setupVerticalStackView()
    setupHorizontalStacks(tableIndex: tableIndex)
}

func setupVerticalStackView() {
    contentView.addSubview(mainStack)
    
    //constraints
    mainStack.topAnchor.constraint(equalTo:  contentView.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
    mainStack.bottomAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
    mainStack.leadingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
    mainStack.trailingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
}

func setupHorizontalStacks(tableIndex: Int) {
    let scaleArray: [ScaleModel] = cellScaleData.createArray()
    
    for index1 in 0...5 {
        let horizontalStackView = UIStackView()
        mainStack.addArrangedSubview(horizontalStackView)
        horizontalStackView.translatesAutoresizingMaskIntoConstraints = false
        horizontalStackView.axis = .horizontal
        horizontalStackView.spacing = 1
        horizontalStackView.alignment = .center
        horizontalStackView.distribution = .fillEqually
        horizontalStackView.leadingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
        horizontalStackView.trailingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
        
        switch index1 {
        case 1 :
            createScaleName(scale: scaleArray[tableIndex], Hstack: horizontalStackView)
        case 2 :
            createRHLabels(scale: scaleArray[tableIndex], Hstack: horizontalStackView)
        case 3 :
            createLetterLabels(scale: scaleArray[tableIndex], Hstack: horizontalStackView)
        case 4 :
            createLHLabels(scale: scaleArray[tableIndex], Hstack: horizontalStackView)
        default:
            print ("spacer")
        }
    }
}

func createScaleName(scale: ScaleModel, Hstack: UIStackView) {
    let label = UILabel()
    label.text = scale.scaleName
    label.textColor = .black
    label.textAlignment = .center
    Hstack.alignment = .center
    Hstack.addArrangedSubview(label)
}

func createRHLabels(scale: ScaleModel, Hstack: UIStackView) {
    for index2 in 0...scale.scaleFingeringRH.count - 1 {
        let label = UILabel()
        label.text = "\(scale.scaleFingeringRH[index2])"
        label.textColor = .black
        Hstack.addArrangedSubview(label)
    }
}

func createLetterLabels(scale: ScaleModel, Hstack: UIStackView) {
    for index2 in 0...scale.scaleLetters.count - 1 {
        let label = UILabel()
        label.text = "\(scale.scaleLetters[index2])"
        label.textColor = .black
        Hstack.addArrangedSubview(label)
    }
}

func createLHLabels(scale: ScaleModel, Hstack: UIStackView) {
    for index2 in 0...scale.scaleFingeringLH.count - 1 {
        let label = UILabel()
        label.text = "\(scale.scaleFingeringLH[index2])"
        label.textColor = .black
        Hstack.addArrangedSubview(label)
    }
}

}

struct ScaleModel {

var scaleName: String
var scaleFingeringRH: [Int]
var scaleFingeringLH: [Int]
var scaleLetters: [String]

}

class ScaleData {
let cMajorScale: ScaleModel = ScaleModel(scaleName: “C Major”, scaleFingeringRH: [1,2,3,1,2,3,4,5], scaleFingeringLH: [5,4,3,2,1,3,2,1], scaleLetters: [“C”,“D”,“E”,“F”,“G”,“A”,“B”,“C”])

let gMajorScale: ScaleModel = ScaleModel(scaleName: "G Major", scaleFingeringRH: [1,2,3,1,2,3,4,5], scaleFingeringLH: [5,4,3,2,1,3,2,1], scaleLetters: ["G","A","B","C","D","E","F#","G"])

let dMajorScale: ScaleModel = ScaleModel(scaleName: "D Major", scaleFingeringRH: [1,2,3,1,2,3,4,5], scaleFingeringLH: [5,4,3,2,1,3,2,1], scaleLetters: ["D","E","F#","G","A","B","C#","D"])

let aMajorScale: ScaleModel = ScaleModel(scaleName: "A Major", scaleFingeringRH: [1,2,3,1,2,3,4,5], scaleFingeringLH: [5,4,3,2,1,3,2,1], scaleLetters: ["A","B","C#","D","E","F#","G#","A"])

let eMajorScale: ScaleModel = ScaleModel(scaleName: "E Major", scaleFingeringRH: [1,2,3,1,2,3,4,5], scaleFingeringLH: [5,4,3,2,1,3,2,1], scaleLetters: ["E","F#","G#","A","B","C#","D#","E"])

let bMajorScale: ScaleModel = ScaleModel(scaleName: "B Major", scaleFingeringRH: [1,2,3,1,2,3,4,5], scaleFingeringLH: [4,3,2,1,4,3,2,1], scaleLetters: ["B","C#","D#","E","F#","G#","A#","B"])

let cbMajorScale: ScaleModel = ScaleModel(scaleName: "C Major", scaleFingeringRH: [1,2,3,1,2,3,4,5], scaleFingeringLH: [4,3,2,1,4,3,2,1], scaleLetters: ["Cb","Db","Eb","Fb","Gb","Ab","Bb","Cb"])


func createArray() -> [ScaleModel] {
    
    let theArray: [ScaleModel] = [cMajorScale, gMajorScale, dMajorScale, aMajorScale, eMajorScale, bMajorScale, cbMajorScale]

return theArray
}
}

Its most probably because of your custom tableview cell… You need to reset the values to nil first before you assign them again

So on your initializer you can set content, views, images to nil first so it can reuse the cell fully

@fuerte.francis thanks! I ended up having to run this loop to manually scrub the cell clean lol!

//check if first run of setup has run so that a mainStack actually exists to clean
if setupcomplete == true {
//scrub the cell clean!
for _ in 0…5 {
mainStack.subviews[0].removeFromSuperview()
}
}
mainStack.removeFromSuperview()