Home > Enterprise >  tableview/tableviewcell weird behavior with labels.isHidden
tableview/tableviewcell weird behavior with labels.isHidden

Time:10-24

I have a game where I want to show the history in a tableview. The game can be played exact with 4 players. The results of winners/losers can vary between 2w/2l, 3w/1l or 1w/3l.

Therefore I created a custom cell as a XIB, where I placed 3 labels (each for winner&losers, so 6 labels in total) in a stackview and I hide always 2 by default. Then, when I have more than one winner/loser I will unhide them and set the names.

But somehow my code does things I don't understand. I tried to debug my code but if it runs slowly it seems to be okay. I don't get it.

My Players struct is just a small part of my Realm object. Also the whole allPlayers array is just dummy data, usually I fetch it from realm.

struct Players {
    let round: Int
    let name: String
    let winner: Bool
    let loser: Bool
}

So I have setup my ViewController standardly as follows:

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    
    let allPlayers: [Players] = [Players(round: 1, name: "Mike", winner: false, loser: true),     // Round 1 2:2
                                 Players(round: 1, name: "Peter", winner: false, loser: true),
                                 Players(round: 1, name: "Tim", winner: true, loser: false),
                                 Players(round: 1, name: "Levi", winner: true, loser: false),
                                 Players(round: 2, name: "Mike", winner: false, loser: true),     // Round 2 1:3
                                 Players(round: 2, name: "Peter", winner: false, loser: true),
                                 Players(round: 2, name: "Tim", winner: false, loser: true),
                                 Players(round: 2, name: "Levi", winner: true, loser: false),
                                 Players(round: 3, name: "Mike", winner: true, loser: false),     // Round 3 3:1
                                 Players(round: 3, name: "Peter", winner: true, loser: false),
                                 Players(round: 3, name: "Tim", winner: true, loser: false),
                                 Players(round: 3, name: "Levi", winner: false, loser: true),
                                 Players(round: 4, name: "Mike", winner: false, loser: true),     // Round 4 2:2
                                 Players(round: 4, name: "Peter", winner: false, loser: true),
                                 Players(round: 4, name: "Tim", winner: true, loser: false),
                                 Players(round: 4, name: "Levi", winner: true, loser: false),
                                 Players(round: 5, name: "Mike", winner: false, loser: true),     // Round 5 1:3
                                 Players(round: 5, name: "Peter", winner: false, loser: true),
                                 Players(round: 5, name: "Tim", winner: false, loser: true),
                                 Players(round: 5, name: "Levi", winner: true, loser: false),
                                 Players(round: 6, name: "Mike", winner: true, loser: false),     // Round 6 3:1
                                 Players(round: 6, name: "Peter", winner: true, loser: false),
                                 Players(round: 6, name: "Tim", winner: true, loser: false),
                                 Players(round: 6, name: "Levi", winner: false, loser: true),
                                 Players(round: 7, name: "Mike", winner: true, loser: false),     // Round 7 3:1
                                 Players(round: 7, name: "Peter", winner: true, loser: false),
                                 Players(round: 7, name: "Tim", winner: true, loser: false),
                                 Players(round: 7, name: "Levi", winner: false, loser: true),
                                 Players(round: 8, name: "Mike", winner: false, loser: true),     // Round 8 1:3
                                 Players(round: 8, name: "Peter", winner: false, loser: true),
                                 Players(round: 8, name: "Tim", winner: false, loser: true),
                                 Players(round: 8, name: "Levi", winner: true, loser: false),
                                 Players(round: 9, name: "Mike", winner: false, loser: true),     // Round 9 1:3
                                 Players(round: 9, name: "Peter", winner: false, loser: true),
                                 Players(round: 9, name: "Tim", winner: false, loser: true),
                                 Players(round: 9, name: "Levi", winner: true, loser: false),
                                 Players(round: 10, name: "Mike", winner: false, loser: true),     // Round 10 2:2
                                 Players(round: 10, name: "Peter", winner: false, loser: true),
                                 Players(round: 10, name: "Tim", winner: true, loser: false),
                                 Players(round: 10, name: "Levi", winner: true, loser: false),
                                 Players(round: 11, name: "Mike", winner: false, loser: true),     // Round 11 2:2
                                 Players(round: 11, name: "Peter", winner: false, loser: true),
                                 Players(round: 11, name: "Tim", winner: true, loser: false),
                                 Players(round: 11, name: "Levi", winner: true, loser: false),
                                 Players(round: 12, name: "Mike", winner: true, loser: false),     // Round 12 3:1
                                 Players(round: 12, name: "Peter", winner: true, loser: false),
                                 Players(round: 12, name: "Tim", winner: true, loser: false),
                                 Players(round: 12, name: "Levi", winner: false, loser: true)]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        let nib = UINib.init(nibName: "TableViewCell", bundle: nil)
        self.tableView.register(nib, forCellReuseIdentifier: "winLooseCell")
    }
}

Because I fetch the data from Realm I made a separate class handler to manage the results and so I only get back arrays of names of the winners/losers.

class Handler {
    var winners: [String] = []
    var losers: [String] = []
    
    func getWinners(round: Int,dataBase: [Players]) -> [String] {
        // Filtercode is just boilerplate, is dunno by realm
        let filtered = dataBase.filter{ dataBase in
            return dataBase.round == round
        }
        for i in 0...filtered.count - 1 {
            if filtered[i].winner {
                winners.append(filtered[i].name)
            }
        }
        return winners
    }
    
    func getLosers(round: Int,dataBase: [Players]) -> [String] {
        // Filtercode is just boilerplate, is dunno by realm
        let filtered = dataBase.filter{ dataBase in
            return dataBase.round == round
        }
        for i in 0...filtered.count - 1{
            if filtered[i].loser {
                losers.append(filtered[i].name)
            }
        }
        return losers
    }
}

And of course my tableView extension to create the whole thing

// MARK: Extension
extension ViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return (allPlayers.count / 4)
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let handler = Handler()
        
        if indexPath.row == 10 {
            // do nothing - just for a debugging breakpoint
        }
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "winLooseCell") as! TableViewCell
        
        let winner = handler.getWinners(round: indexPath.row   1, dataBase: allPlayers)
        for i in 0...winner.count - 1 {
            cell.winnerNameLabels[i].isHidden = false
            cell.winnerNameLabels[i].text = winner[i]
        }
        
        let loser = handler.getLosers(round: indexPath.row   1, dataBase: allPlayers)
        for i in 0...loser.count - 1 {
            cell.loserNameLabels[i].isHidden = false
            cell.loserNameLabels[i].text = loser[i]
        }
        
        cell.roundLabel.text = "\(indexPath.row   1)"
        
        return cell
    }
}

The class for the tableViewCell

class TableViewCell: UITableViewCell {
    @IBOutlet var winnerNameLabels: [UILabel]!
    @IBOutlet var loserNameLabels: [UILabel]!
    @IBOutlet weak var roundLabel: UILabel!
}

and the Xib File enter image description here

and for some reason after I load the simulator I get in round 11 this weird behavior

enter image description here

Anyone got an idea why and how I can solve this issue?

CodePudding user response:

You're forgetting that cells are reused. A cell that appears in a certain row can reappear later in a different row — as you scroll, for instance. Therefore you must take account of what row this is, completely, in your logic for configuring the cell.

Thus, in cellForRowAt, we see that your code might say

 cell.winnerNameLabels[i].isHidden = false

But at no time do you ever say

 cell.winnerNameLabels[i].isHidden = true

Therefore once you have unhidden a label for this cell, it remains unhidden no matter what row this cell is reused in, for the rest of the lifetime of the app.

  • Related