swiftapi

Getting an empty variable from API parsing


I started to work with API and got some problems that I'm not able to fix.

That's code related to my problem:

// MARK: - ProPlayerElement
struct ProPlayerElement: Codable {
    let name, avatarfull, personaname: String?
    let fantasyRole: Int?
    let teamName: String?

    enum CodingKeys: String, CodingKey {
        case name, avatarfull, personaname
        case fantasyRole = "fantasy_role"
        case teamName = "team_name"
    }
}

typealias ProPlayers = [ProPlayerElement]
class ApiManager {
    
    static let shared = ApiManager()
    
    func getInformation(completion: @escaping (ProPlayers) -> Void) {
        let request = ApiType.proPlayers.request
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data, let players = try?JSONDecoder().decode(ProPlayers.self, from: data) {
                completion(players)
            } else {
                completion([])
            }
        }
        task.resume()
    }
}
var heroNames = [String] ()
    func heroesNames () {
        ApiManager.shared.getInformation { players in
            for i in 0..<players.count-1 {
                self.heroNames.append(players[i].name!)
            }
        }
    }

So, about the problem: when i use the last function (heroesNames) my variable doesn't save any info as if this function never existed at all.

I did some test and now I know that everything inside

ApiManager.shared.getInformation { ProPlayers in

}

works perfect but outside this expression zero results

added print((self.heroNames)) (and changed count-1, it was misprint) before append and after append, works fine

    func heroesNames () {
    ApiManager.shared.getInformation { players in
        for i in 0..<players.count {
            print("before append\(self.heroNames)")
            self.heroNames.append(players[i].name!)
            print("after append\(self.heroNames)")
        }
    }
}

before append[] after append["TZY"] before append["TZY"] after append["TZY", "YrikGood"] before append["TZY", "YrikGood"] after append["TZY", "YrikGood", "Newsham"]


Solution

  • try something like this, to deal with your asynchronous func heroesNames(...) :

     func heroesNames(completion: @escaping ([String]) -> Void) { // <-- here
         ApiManager.shared.getInformation { players in
             completion(players.map{$0.name}) // <-- here
         }
     }
    

    And use it like this:

     heroesNames() { names in
         print("\(names.count)") // for testing
         self.heroNames = names  // <-- only here, not before
         // alternatively
         // self.heroNames.append(contentsOf: names)
     }
    

    Of course, you could do away with func heroesNames(...) and use this instead:

    ApiManager.shared.getInformation { players in
        self.heroNames = players.map{$0.name}
    }