hi,
just getting caught up on this ... took a few days off ...
japio: it's clear that when you closed out the last thread, you were satisfied with the Database singleton and that you wanted to persist the list of players. it's no surprise now to find out that things don't work because you never asked to persist myRoster and draftOrder, nor did the Database ever handle these.
Claude31's suggestions should work fine, and if you're satisfied with them, that's cool with me. and whether you persist data to a file in the Documents directory or as data in UserDefaults, it probably does not matter for the size of this app.
however, with all due respect to my friend Claude31, i think you really want to move to a file-based model managed by the Database singleton, and eventually begin to use a UIDocument model to allow auto-saving.
so i would suggest all of what appears below. i'm sorry for the length, but the specificity really is necessary, and i'd encourage you to read through all of it and, if it makes sense, then consider using it in the future.
(1) let the Database singleton manage all data centrally, rather than rely on hooks in the Application Delegate and adding portions of the data management throughout your code to save other lists.
(2) instead of keeping three separate lists, one of type PlayerData and two of type String, simplify by making all lists of type PlayerData (and let whatever view controllers access those lists decide how they want to display them, using the name, the team, and the position).
(3) keep all the internals of how the lists are managed within the Database singleton; and to accomplish this, i'd propose extending the definition of PlayerData to include two Int values, one perhaps named "rosterPosition" to indicate the position at which a player appears in the myRoster list, and one perhaps named "draftPosition" to indicate the position at which a player appears in the draftOrder list. use -1 as a value to indicate that a player does not appear in a list.
in short, there will be only one list of players ⚠ all the draft and roster information will be incorporated into the PlayerData records directly in this single list.
(4) expand the Database singleton to have methods to provide myRoster and draftOrder as needed in your program with
func rosterList() -> [PlayerData] {
let rosteredPlayers = allPlayers.filter({ $0.rosterPosition >= 0 })
return rosteredPlayers.sorted(by: { $0.rosterPosition < $1.rosterPosition })
}
func draftList() -> [PlayerData] {
let draftedPlayers = allPlayers.filter({ $0.draftPosition >= 0 })
return draftedPlayers.sorted(by: { $0.draftPosition < $1.draftPosition })
}
(5) expand the Database singleton to allow moving a player onto one of these lists (which, from your code, always seems to be an "appending"). this requires a quick computation to figure out where in the list to place an addition:
func addToRosterList(player: PlayerData) {
let maxRosteredIndex = allPlayers.map({ $0.rosterPosition }).max()!
player.rosterPosition = maxRosteredIndex + 1
}
func addToDraftList(player: PlayerData) {
let maxDraftedIndex = allPlayers.map({ $0.draftPosition }).max()!
player.draftPosition = maxDraftedIndex + 1
}
(6) your addPlayer() function then simplifies:
func addPlayer(index: IndexPath) {
// remove this line: _ = top30QuarterbacksTable.cellForRow(at: index)
let player = objectsArray[index.row]
// remove this line: let name: String = objectsArray[index.row].name
// remove this line: let team: String = objectsArray[index.row].team
// remove this line: let position: String = objectsArray[index.row].position
player.strikeThrough = true
player.accessory = true
player.color = true
Database.shared.addToRosterList(player: player)
// remove this line: if myRoster == [] {
// remove this line: myRoster?.insert("\(name), \(team) - \(position)", at: 0)
// remove this line: } else {
// remove this line: myRoster?.append("\(name), \(team) - \(position)")
// remove this line: }
Database.shared.addToDraftList(player: player)
// remove this line: if draftOrder == [] {
// remove this line: draftOrder?.insert("\(name), \(team) - \(position)", at: 0)
// remove this line: } else {
// remove this line: draftOrder?.append("\(name), \(team) - \(position)")
// remove this line: }
top30QuarterbacksTable.reloadData()
Database.shared.changeMade()
}
that does it in principle, except that you'll need to understand the implications:
(a) (EDIT: you'll need to update the PlayerData class definition)
class PlayerData: Codable {
var num: Int = 0
var name: String = ""
var team: String = ""
var position: String = ""
var strikeThrough: Bool = false
var color: Bool = false
var accessory: Bool = false
var rosterPosition: Int = -1 // not on the roster
var draftPosition: Int = -1 // not drafted
init(num: Int, name: String, team: String, position: String) {
self.num = num
self.name = name
self.team = team
self.position = position
}
}
(b) in any view controller where you display the roster and draft order, you'll start with
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated: animated)
myRoster = Database.shared.rosterList()
draftOrder = Database.shared.draftList()
}
(c) in such a viewController, you would need to build out whatever string you want to appear in cellForRow(at:) separately, because myRoster and draftOrder will now be lists of PlayerData and not lists of String. for example, it's no longer
let str = myRoster[index]
but instead
let player = myRoster[index]
let str = "\(player.name), \(player.team) - \(player.position)"
(d) finally, if you make all these changes and adopt this program, you should expect to run into errors when you run your app, because we have changed the definition of PlayerData. it's now incompatible with what is stored on disk and/or in UserDefaults. simply delete the app from the simulator or iOS device, then run again from XCode with a fresh copy of the app and no data yet persisted. you'll be back at the beginning.
that's a lot to digest. i hope it makes some sense to you, and it will greatly simplify a lot of your code.
hope that helps,
DMG