How do I create an array of a class?

How do I create an array of a class?


I am managing my data in a singleton database.


The structure is the following:


Main view - Has a table view to select top quarterbacks, top running backs, etc. When the row is clicked, it segues to another view controller displaying the top quarterbacks, running backs, etc.


Top quarterbacks view, runningbacks view, etc.: When the row is swiped, two buttons display - Add, taken -

- Add will add that player to my team.

- Taken will mark the player as taken and add that player to draft order.


After the draft is complete, I have a button called 'add to league'.

- Add to league button will segue to another view controller.


Add league view: This view has a text field to name the league and then a button to add the league.

- Add button adds the league name and segues to another view controller to view the added leagues.


My leagues view: This is a table view that has the added league names. If there are more than one added league, then there will be more than one row in the table view. What I want is when a row is tapped to segue to another view controller with a table view and display that added leagues players and at the same time to reset the draft.

This is how I get the players on my team:


class PlayerData: Codable {
    var num: Int = 0
    var numPosPick: Int = 0
    var numRookie: Int = 0
    var name: String = ""
    var team: String = ""
    var position: String = ""
    var rosterPosition: Int = -1
    var draftPosition: Int = -1
    var isTopPlayer: Bool
    var isRookie: Bool
    
    var isRostered: Bool { return rosterPosition >= 0 }
    var isDrafted: Bool { return draftPosition >= 0 }
    
    init(num: Int, numPosPick: Int, numRookie: Int, name: String, team: String, position: String, isTopPlayer: Bool, isRookie: Bool) {
        self.num = num
        self.numPosPick = numPosPick
        self.numRookie = numRookie
        self.name = name
        self.team = team
        self.position = position
        self.isTopPlayer = isTopPlayer
        self.isRookie = isRookie
    }
}
class Database_2019 {
    
    static let shared = Database_2019()
    
    var myLeagues: [String] = []
    
    var myleaguePlayers: [PlayerData]
    
    var myLeaguePlayersData: [[PlayerData]]
    
    func addPlayersToLeague(league: String) {
        myleaguePlayers = rosterList()
        
        if myLeagues == [] {
            myLeagues.insert(league, at: 0)
            myLeaguePlayersData.insert(myleaguePlayers, at: 0)
        } else {
            myLeagues.append(league)
            myLeaguePlayersData.append(myleaguePlayers)
        }
        resetDraft()
    }
    
    // All players and leagues 2019
    fileprivate var allPlayers: [PlayerData]
    fileprivate var allPlayersReset: [PlayerData] // To hold the reset properties.
    
    fileprivate func playerDataURL() -> URL {
        let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
        return documentDirectoryURL.appendingPathComponent("playerData_2019.json")
    }
    
    fileprivate func leaguesDataURL() -> URL {
        let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
        return documentDirectoryURL.appendingPathComponent("leaguesData_2019.json")
    }
    
    fileprivate func leaguePlayersDataURL() -> URL {
        let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
        return documentDirectoryURL.appendingPathComponent("leaguePlayersData_2019.json")
    }
    
    // Save players and leagues to disk
    fileprivate func playersWriteToDisk() {
        do {
            let data = try JSONEncoder().encode(allPlayers)
            try data.write(to: playerDataURL())
        } catch let error as NSError {
            NSLog("Error reading file: \(error.localizedDescription)")
        }
    }
    
    fileprivate func leaguesWriteToDisk() {
        do {
            let data = try JSONEncoder().encode(myLeagues)
            try data.write(to: leaguesDataURL())
        } catch let error as NSError {
            NSLog("Error reading file: \(error.localizedDescription)")
        }
    }
    
    fileprivate func leaguesPlayersWriteToDisk() {
        do {
            let data = try JSONEncoder().encode(myLeaguePlayersData)
            try data.write(to: leaguePlayersDataURL())
        } catch let error as NSError {
            NSLog("Error reading file: \(error.localizedDescription)")
        }
    }
    
    // Load players and leagues from disk
    fileprivate func playersReadFromDisk() -> [PlayerData]? {
        let filePlayerURL = playerDataURL()
        guard FileManager.default.fileExists(atPath: filePlayerURL.path) else {
            return nil
        }
        do {
            let fileContents = try Data(contentsOf: filePlayerURL)
            let list = try JSONDecoder().decode([PlayerData].self, from: fileContents)
            return list
        } catch let error as NSError {
            NSLog("Error reading file: \(error.localizedDescription)")
        }
        return nil
    }
    
    fileprivate func leaguesReadFromDisk() -> [String]? {
        let fileLeaguesURL = leaguesDataURL()
        guard FileManager.default.fileExists(atPath: fileLeaguesURL.path) else {
            return nil
        }
        do {
            let fileContents = try Data(contentsOf: fileLeaguesURL)
            let list = try JSONDecoder().decode([String].self, from: fileContents)
            return list
        } catch let error as NSError {
            NSLog("Error reading file: \(error.localizedDescription)")
        }
        return nil
    }
    
    fileprivate func leaguePlayersReadFromDisk() -> [[PlayerData]]? {
        let fileLeaguePlayersURL = leaguePlayersDataURL()
        guard FileManager.default.fileExists(atPath: fileLeaguePlayersURL.path) else {
            return nil
        }
        do {
            let fileContents = try Data(contentsOf: fileLeaguePlayersURL)
            let list = try JSONDecoder().decode([[PlayerData]].self, from: fileContents)
            return list
        } catch let error as NSError {
            NSLog("Error reading file: \(error.localizedDescription)")
        }
        return nil
    }
    
    // Player lists    
    func playerList(position: String) -> [PlayerData] {
        return allPlayers.filter({ $0.position == position })
    }
    
    func playerList(topPlayer: Bool) -> [PlayerData] {
        return allPlayers.filter({ $0.isTopPlayer == topPlayer })
    }
    
    func playerList(rookie: Bool) -> [PlayerData] {
        return allPlayers.filter({ $0.isRookie == rookie })
    }
    
    // Roster lists/My team lists
    func rosterList() -> [PlayerData] {
        let rosteredPlayers = allPlayers.filter { ($0.rosterPosition >= 0)}
        return rosteredPlayers.sorted(by: { $0.rosterPosition < $1.rosterPosition })
    }
    
    func rosterArray() -> [PlayerData] {
        let roster = rosterList()
        return roster
    }
    
    func addToRosterList(player: PlayerData) {
        let maxRosteredIndex = allPlayers.map({ $0.rosterPosition }).max()!
        player.rosterPosition = maxRosteredIndex + 1
    }
    
    fileprivate func removeFromRosterList(player: PlayerData) {
        let currentRosterPosition = player.rosterPosition
        player.rosterPosition = -1 // No longer on the rosterList. Gets all players on roster at a higher index.
        let higherNumberedRosterPlayers = allPlayers.filter({ $0.rosterPosition > currentRosterPosition}) // Their rosterPositions have now gone down by one.
        
        for otherPlayer in higherNumberedRosterPlayers {
            otherPlayer.rosterPosition -= 1 // Decrease position by 1.
        }
    }
    
    // draft List
    func draftList() -> [PlayerData] {
        let draftedPlayers = allPlayers.filter({ $0.draftPosition >= 0 })
        return draftedPlayers.sorted(by: { $0.draftPosition < $1.draftPosition })
    }
    
    func addToDraftList(player: PlayerData) {
        let maxDraftedIndex = allPlayers.map({ $0.draftPosition }).max()!
        player.draftPosition = maxDraftedIndex + 1
    }
    
    fileprivate func removeFromDraftList(player: PlayerData) {
        let currentDraftPosition = player.draftPosition
        player.draftPosition = -1 // No longer on the rosterList. Gets all players on roster at a higher index.
        let higherNumberedRosterPlayers = allPlayers.filter({ $0.draftPosition > currentDraftPosition}) // Their rosterPositions have now gone down by one.
                
        for otherPlayer in higherNumberedRosterPlayers {
            otherPlayer.draftPosition-=1 // Decrease position by 1.
        }
    }
    
    func removeFromLists(player: PlayerData) {
        removeFromRosterList(player: player)
        removeFromDraftList(player: player)
    }
    
    fileprivate func removeFromRosterListToBeAdded_2019(player: PlayerData) {
        let currentRosterPosition = player.rosterPosition
        player.rosterPosition = -1 // No longer on the rosterList. Gets all players on roster at a higher index.
        let higherNumberedRosterPlayers = allPlayers.filter({ $0.rosterPosition > currentRosterPosition}) // Their rosterPositions have now gone down by one.
        
        for otherPlayer in higherNumberedRosterPlayers {
            otherPlayer.rosterPosition -= 1 // Decrease position by 1.
        }
    }
    
    // Leagues list to be added to My Leagues
    func leaguesList() -> [String] {
        return myLeagues
    }
    
    func leaguesArray() -> [String] {
        let leagues = leaguesList()
        return leagues
    }
    
    fileprivate func removeFromLeaguesList(player: String) {
        let index = IndexPath.Element()
        myLeagues.remove(at: index)
    }
    
    func removeLeague(league: String) {
        removeFromLeaguesList(player: league)
    }
    
    // Reset the draft
    func resetDraft() {
        allPlayers = allPlayersReset
        changeMade()
    }
    
    // Executed when a change is made
    func changeMade() {
        playersWriteToDisk()
        leaguesWriteToDisk()
    }

In line 9 of class Database_2019, I created an array of the class PlayerData but it isn't working.


This is what class myLeague_2019 looks like:


class MyLeague_2019: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    var players: [[PlayerData]] = [[]]
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        players = Database_2019.shared.myLeaguePlayersData
        
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return players[section].count
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return players.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let players = Database_2019.shared.myLeaguePlayersData[indexPath.section][indexPath.row]
        let cell = table.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        
        cell.textLabel?.text = "\(indexPath.row+1).  \(players.name), \(players.team) - \(players.position)"
        cell.textLabel?.adjustsFontSizeToFitWidth = true
        cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
        return cell
    }
    
    @IBOutlet weak var table: UITableView!
}

Replies

In line 9 of class Database_2019, I created an array of the class PlayerData but it isn't working.


What do you mean. What do you expect ? What do you get ?

In fact, you don't want to create an array of class, but more probably an array of instances of class. Right ?


Could you explain what the arrays are:

var myLeagues: [String] = []

That is the list of leagues names ?

var myleaguePlayers: [PlayerData]

That is a list of players


var myLeaguePlayersData: [[PlayerData]]

What is this ? It is equivalent to [myleaguePlayers]

Why an array ? An item for each league ?

If so, the name is really not explicit. Something like allLeaguesPlayersData would be more meaningful.

var myLeagues: [String] is the list of league names.


var myLeaguePlayers: [PlayerData} is the players.


var myLeaguePlayersData: [[PlayerData]] is an array of the players.


For instance, I want to be able to append myLeaguesPlayers to myLeaguePlayersData when a league is added but I want the added myLeaguePlayers to be connected to the added myLeagues.


The result I want is when the added leagues row is clicked, it will segue to another view controller and load the connected myLeaguePlayersData element inb a table.


What is your sugestion on how to do this?

Sorry, don't understand the difference between the 2


var myLeaguePlayers: [PlayerData} is the players. => It is an array, of players ?


var myLeaguePlayersData: [[PlayerData]] is an array of the players.


The result I want is when the added leagues row is clicked, it will segue to another view controller and load the connected myLeaguePlayersData element inb a table.


Did you implement the didSelect delegate func for the tableView ?

Where is it in your code ?

Does your code compile ? Class 'Database_2019' has no initializers.


So you should initialize all properties, such as

    var myleaguePlayers: [PlayerData] = []
    var myLeaguePlayersData: [[PlayerData]] = []

var myLeaguePlayers is an array of players.


var myLeaguePlayersData is an array of the added leagues players.


myLeaguePlayers = [Aaron Rodgers, GB - QB, Alvin Kamara, NO - RB, Tyreek Hill, KC - WR]

myLeaguePlayersData = [[Patrick Mahomes, KC - QB, David Johnson, ARI - RB, Michael Thomas, NO - WR], [Matt Ryan,
ATL - QB, Joe Mixon, CIN - RB], [Aaron Rodgers, GB - QB, Alvin Kamara, NO - RB, Tyreek Hill, KC - WR]]


myLeaguePlayers is the current players in the league. I want to append myLeaguePlayers to myLeaguePlayersData.


I do have myLeaguePlayers and myLeaguePlayersData initialized. I didn't show it but here it is:


init() {
     myLeagues = [String]()
     myleaguePlayers = [PlayerData]()
     myLeaguePlayersData = [[PlayerData]]()
}

Please, could you read the posts completely and answer all questions ? That will make it easier:

1. Did you implement the didSelect delegate func for the tableView ?

2. Where is it in your code ?


You said:

The result I want is when the added leagues row is clicked, it will segue to another view controller and load the connected myLeaguePlayersData element inb a table.

3. you mean a table in the destination VC ?

4. Which class is this VC ?

5. Do you want to pass the whole myLeaguePlayersData to the destination ?

If so, you simply need to declare a property in the destination

var transferedData : [[PlayerData]] ?

And set this in prepare of the origin controller

destVC.transferedData = myLeaguePlayersData


For the dataStructures, there is still a question

var myLeaguePlayersData is an array of the added leagues players.

So, why do you declare as an array of arrays and not simply an array of PlayerData ?


What is the first index ?

myLeaguePlayersData = [

[Patrick Mahomes, KC - QB, David Johnson, ARI - RB, Michael Thomas, NO - WR],

[Matt Ryan, ATL - QB, Joe Mixon, CIN - RB],

[Aaron Rodgers, GB - QB, Alvin Kamara, NO - RB, Tyreek Hill, KC - WR]

]


Do you want to keep memory that those players were added as a group, like [Patrick Mahomes, KC - QB, David Johnson, ARI - RB, Michael Thomas, NO - WR] ?

1. I tried implementing didSelectRowAt function but how do I implement it that when a row is selected with the league name that it will segue to another view controller load the players for that selected league in a table view?


3. Yes, table in destination VC. I setup a segue in storyboard to segue to another view controller to load myLeaguePlayersData.


4. The destination VC class is MyLeague_2019

class MyLeague_2019: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    var players: [[PlayerData]] = [[]]
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        players = Database_2019.shared.myLeaguePlayersData
        
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return players[section].count
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return players.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let players = Database_2019.shared.myLeaguePlayersData[indexPath.section][indexPath.row]
        let cell = table.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        
        cell.textLabel?.text = "\(indexPath.row+1).  \(players.name), \(players.team) - \(players.position)"
        cell.textLabel?.adjustsFontSizeToFitWidth = true
        cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
        return cell
    }
    
    @IBOutlet weak var table: UITableView!
}


5. Yes, I want to pass the whole myLeaguePlayersData to the destination.

Yes, I do need to declare as an array of PlayerData.

Yes, I do want to keep in memory that those players are added as a group.

For 1.


You should habe something like this (I imagined the segie ID is "SegueFromCell"


func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {

    self.performSegue(withIdentifier: "SegueFromCell", sender:self
}

in prepare (it is not clear what is the class of the destVC, the one that will have a var transferedData declared, is it MyLeague2029 ?):


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
        if segue.identifier == "SegueFromCell" {
            if let destVC = segue.destination as? TheClassOfDestViewController { 
               destVC.transferedData = myLeaguePlayersData
            }
        }
}