Search code examples
swiftcodabledecodable

Instance method requires that 'classname' conform to 'Decodable'


I'm trying to decode a JSON response as a custom type, that I believe conforms to Decodable.

These are the codable structs that I am using

struct ResultSet: Codable {
    var name: String
    var headers: [String]
    var rowSet: [String]
}

struct Scoreboard: Codable {
    var resultSets: [ResultSet]
}

And this is the code I'm using to get the JSON from the response

func loadNbaScoreboardData<Scoreboard>() -> Scoreboard {
    
    //var data1: Data
    
    let formatter = DateFormatter()
    formatter.dateFormat = "MM/dd/yyyy"
    let formattedDate = formatter.string(from: Date())
    
    let url = URL(string: "https://stats.nba.com/stats/scoreboard/?GameDate=\(formattedDate)&LeagueID=00&DayOffset=100")
    var request = URLRequest(url: url!)
    request.httpMethod = "GET"
    request.setValue("stats.nba.com", forHTTPHeaderField: "host")
    request.setValue("application/json", forHTTPHeaderField: "Accept")
    request.setValue("stats", forHTTPHeaderField: "x-nba-stats-origin")
    request.setValue("x-nba-stats-origin", forHTTPHeaderField: "Referer")
    
    var retData: Scoreboard
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data else{ return }
        
        do {
            let decodedData = try JSONDecoder().decode(Scoreboard.self, from: data)
            retData = decodedData
        } catch {
            fatalError(error)
        }
    }.resume()
    
    return retData
}

The error I get is Instance method 'decode(_:from:)' requires that 'Scoreboard' conform to 'Decodable'

I'm following the dev documentation here too https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

What am I doing wrong here?

EDIT: The Scoreboard struct can't be found. I've added the full method


Solution

  • In your code Scoreboard is a generic type (not the concrete type Scoreboard). You can fix the error by adding Codable conformance

    func loadNbaScoreboardData<Scoreboard: Codable>() -> Scoreboard {
    

    But the code won't work anyway because you cannot return something from an asynchronous task.

    I recommend to make the function async

    func loadNbaScoreboardData() async throws -> Scoreboard {
        
        //var data1: Data
        
        let formatter = DateFormatter()
        formatter.dateFormat = "MM/dd/yyyy"
        let formattedDate = formatter.string(from: Date())
        
        let url = URL(string: "https://stats.nba.com/stats/scoreboard/?GameDate=\(formattedDate)&LeagueID=00&DayOffset=100")
        var request = URLRequest(url: url!)
        request.httpMethod = "GET"
        request.setValue("stats.nba.com", forHTTPHeaderField: "host")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        request.setValue("stats", forHTTPHeaderField: "x-nba-stats-origin")
        request.setValue("x-nba-stats-origin", forHTTPHeaderField: "Referer")
        
        let (data, _ ) = try await URLSession.shared.data(for: request)
        return try JSONDecoder().decode(Scoreboard.self, from: data)
    }