How to save the state of a table view?

How do I save the state of a table view after a change to the table view has been made? When I switch to another view and switch back, the table view changes are lost and is back to default. I know there are multiple ways to do this but what is the easiest way? I am thinking core data but how do I do it?

Answered by DelawareMathGuy in 399909022

hi,


great! we've finally now gotten to what i think was your original question of "how to save the state ..." as i said above, "... if you really want to persist this data across application launches ... that's another journey."


what follows below is enough to get things working (albeit maybe not the best way to do this)


step 1: when the Database is first used, populate the allPlayers list from disk, or default to your hard-coded data if we have not yet written anything to disk.


first, change the name of your Data class to, perhaps, PlayerData -- you need to do this because we must use the Foundation class named Data -- and make it conform to the Codable protocol by writing


class PlayerData: Codable { // change name and add Codable


next, add the following functions to the Database class. you'll store the data in the Documents directory with the name playerData.json


fileprivate func playerDataURL() -> URL {
  let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
  return documentDirectoryURL.appendingPathComponent("playerData.json")
}

fileprivate func readFromDisk() -> [PlayerData]? {
  let fileURL = playerDataURL()
  guard FileManager.default.fileExists(atPath: fileURL.path) else {
    return nil
  }

  do {
    let fileContents = try Data(contentsOf: fileURL)
    let list = try JSONDecoder().decode([PlayerData].self, from: fileContents)
    return list
  } catch let error as NSError {
    NSLog("Error reading file: \(error.localizedDescription)")
  }
  return nil
}


also change the init() method of Database slightly to be


init() {
  allPlayers = [PlayerData]()
  if let playerList = readFromDisk() {
    allPlayers = playerList
  } else {
    allPlayers = [
    // then all the data
    ]
  } // don't forget to add a closing curly brace here for the else
} // closes the init() method


step #2: add the following method in Database to be able to write data to disk.


fileprivate func writeToDisk() {
  do {
    let data = try JSONEncoder().encode(allPlayers)
    try data.write(to: playerDataURL())
  } catch let error as NSError {
    NSLog("Error reading file: \(error.localizedDescription)")
  }
}


step #3: you need to detect when changes have been made to the player data. one possible solution: explicitly tell the database that changes have been made whenever you make a change so that it will save to disk. so add the following method to the Database class:


func changeMade() {
  writeToDisk()
}


step #4: wherever in your code you make a change to any individual player, be sure to add a call to changeMade(). example: in addPlayer(), removePlayer(), and markAsTaken(), close the functions with both


top30QuarterbacksTable.reloadData()  // makes the visual changes on screen
Database.shared.changeMade() // triggers the data change on disk


i'm pretty sure i have all the code above correct on reading and writing (???)



hope that helps,

DMG

Yes, I didn't realize I didn't change that. I should have known to change Data to PlayerData. It works great!


Thank you very much for your help.

I am sorry. I changed Data to PlayerData in the data and it works perfectly.


Thank you for your help.

How to save the state of a table view?
 
 
Q