Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TableViewCell doesn't reload as expected

I have a little app that tracks players playing time in a sports game. I have a list of sports games, and you can click into one and start tracking game details. I'm trying to make it so that if a game is in progress and a user goes back to the list of games, that they can't click on another game cell as it overwrites all the current data in the active game.

I've almost made this work. When a game is in progress and I go back to the list of sports games, only the active one is accessible and shows to the user that it's active. But when I go back and reset that game, I expect the tableView of sports games to all be accessible. But they are not. It still shows only one active game and all the other games are inaccessible. I am using tableView.reloadData within viewWillAppear. I've shown the relevant code below also.

// gameViewController -> shows all the games you can track
override func viewWillAppear(_ animated: Bool) {
    self.tableView.reloadData()
    for game in fetchedResultsController.fetchedObjects! {
        print("Game Opposition is \(game.opposition)")
        print("Is Playing? \(game.isPlaying)")
        print("Current Playing Time \(game.currentGameTime)")
        print("----------------------")
    }
}

// game cell view controller -> checks to see if any games are in progress
func isAnyGamesInProgress(games: [Game]) -> Bool {
     let inProgressGames = games.filter({ Int($0.currentGameTime) > 0 && $0.gameComplete == false })
if inProgressGames.isEmpty {
    return false
}
return true
 }

 // configures the games cells in tableview
func configureFixtureCell(fixture: Game){
oppositionLabel.text = "\(fixture.team.name) v \(fixture.opposition)"

// check if any games are currently in progress, if so disable all the other cells
// this prevents a user being mid game and checking an old game and inadvertently updating all the played time values
let games = fixture.team.game?.allObjects as! [Game]

if isAnyGamesInProgress(games: games){
    isUserInteractionEnabled = false
    inPlayLabel.isHidden = true // identifies that this game is in progress
}
// unset the sole game who's in progress
if Int(fixture.currentGameTime) > 0 && !fixture.gameComplete {
    isUserInteractionEnabled = true // makes this cell active
    // show label as green dot
    inPlayLabel.isHidden = false
    inPlayLabel.layer.cornerRadius = 8
    inPlayLabel.layer.masksToBounds = true
    }
}

Now this works when I have a game in progress. I go back to the game list and the active game is accessible and shows the little label and all the other games cells are inactive. But if I go back and reset the game, so it's no longer active, all the games should be displayed and be accessible. But the game that was active is still shown as active and all the other game cells are inaccessible.

I've confirmed that when I've reset the game that it isn't being classed as still active by printing out a message in the isAnyGamesInProgress() call in configureFixtureCell(). So unsure why the rows don't seem to update, especially as I'm reloading the table when the game list controller willAppear()?? and I'm not caching the result of the games NSFecthController :)

I've attached some images to show the console output too. First is the initial load

Initial Load

Game in progress enter image description here

After game resetenter image description here

like image 603
Jonnny Avatar asked Jun 04 '17 16:06

Jonnny


1 Answers

looking at the code, it looks like a reusable cell reset problem.

Try resetting the cell in prepareForReuse() method.

Override it in your cell subclass and it will be called every time when a previously existing cell is dequeued by dequeueReusableCellWithReuseIdentifier.

Example in Swift

class myCell: UITableViewCell {

    ...
    ...
    override func prepareForReuse() {
    // your cleanup code
    }

}
like image 165
Karthik Kumar Avatar answered Nov 15 '22 07:11

Karthik Kumar