I have a CustomType that conforms to Decodable, when I want use it as needed value for my function, Xcode complain that CustomType does not conform to Decodable! Should I explicitly make CustomType conformation happen, I also did it, but it did not solved the issue! What I am missing here?
Error:
Type 'CustomType.Type' cannot conform to 'Decodable'
let stringOfJSON: String = """
{ "name": "SwiftPunk", "age": 35 }
"""
let dataOfJSON: Data? = stringOfJSON.data(using: String.Encoding.utf8)
struct CustomType: Decodable {
enum Codingkeys: String, CodingKey {
case name, age
}
var name: String
var age: Int
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Codingkeys.self)
name = try container.decode(String.self, forKey: .name)
age = try container.decode(Int.self, forKey: .age)
}
}
func decoderFunction<T: Decodable>(dataOfJSON: Data?, customType: T, decodedValue: (T) -> Void) {
if let unwrappedDataOfJSON: Data = dataOfJSON {
let dataJSONDecoder: JSONDecoder = JSONDecoder()
do {
let value: T = try dataJSONDecoder.decode(T.self, from: unwrappedDataOfJSON)
decodedValue(value)
} catch {
print("The Data could not be decoded!")
}
}
}
use case:
decoderFunction(dataOfJSON: dataOfJSON, customType: CustomType.self, decodedValue: { value in
})
CodePudding user response:
The type of the customType
parameter is incorrect. It should be the metatype of T
(T.Type
), not T
.
func decoderFunction<T: Decodable>(dataOfJSON: Data?, customType: T.Type, decodedValue: (T) -> Void) {
...
}
The method was expecting a value of type T
, which should conform to Decodable
, but you were giving it a value of type CustomType.Type
, which doesn't conform to Decodable
(but note that CustomType
does).
Also note that you don't need the customType
parameter at all. T
can be inferred if you specify the type in the closure:
func decoderFunction<T: Decodable>(dataOfJSON: Data?, decodedValue: (T) -> Void) {
...
}
decoderFunction(dataOfJSON: dataOfJSON, decodedValue: { (value: CustomType) in
})
CodePudding user response:
Change the function signature to:
func decoderFunction<T: Decodable>(
dataOfJSON: Data?,
customType: T.Type,
decodedValue: (T) -> Void)
You want to pass in the type of T
not a value of T
CodePudding user response:
As you apparently like to annotate types I would omit the type parameter completely and annotate the type in the closure of the caller function.
Further use the Result
type to handle a potential error and pass the JSON string to the function rather than optional Data
let stringOfJSON: String = """
{ "name": "SwiftPunk", "age": 35 }
"""
struct CustomType: Decodable {
let name: String
let age: Int
}
func decoderFunction<T: Decodable>(json: String, decodedValue: (Result<T,Error>) -> Void) {
decodedValue(Result {
try JSONDecoder().decode(T.self, from: Data(json.utf8))
})
}
And call it
decoderFunction(json: stringOfJSON) { (result : Result<CustomType,Error>) in
switch result {
case .success(let value): print(value)
case .failure(let error): print(error)
}
}