I'm having trouble getting a function call using a generic type to work using a URLSession
DataTaskPublisher
...
The API I'm calling always responds with an HTTP 200, and indicates whether it was successful or not in the JSON via a code
string with an indicator.
I created a protocol
that all response objects conform to, e.g.:
protocol APIResponse: Decodable {
var code: String { get }
}
My actual response will be something like:
struct LoginResponse : APIResponse {
let code: String
let name: String
enum CodingKeys: String, CodingKey {
case code = "code"
case name = "name"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
code = try values.decode(String.self, forKey: .code)
name = try values.decode(String.self, forKey: .name)
}
}
Now I want a function like this that I can use:
private func call<T: APIResponse>(_ endpoint: String, using data: Encodable, providing response: T)
-> AnyPublisher<T, Error> {
let request = createRequest(for: endpoint, using: data)
return session
.dataTaskPublisher(for: request)
.map {
$0.data
}
.decode(type: T.self, decoder: decoder)
.tryMap {
response in
if response.code.suffix(1) != "I" {
throw MyError(message: "Error (code)")
}
return response
}
.eraseToAnyPublisher()
}
So far, so good!
But here's the problem... I want to use it like this:
func login() -> AnyPublisher<String, Error> {
call("login", using: LoginRequest(), providing: LoginResponse)
.map {
$0.name
}
.eraseToAnyPublisher()
}
The compiler complains with Type 'LoginResponse.Type' cannot conform to 'APIResponse'; only struct/enum/class types can conform to protocols
My fix (which works, but is kludgy), it to provide a no-arg init()
for LoginResponse
and call it like this: call("login", using: LoginRequest(), providing: LoginResponse())
Any way to get the Generic to work without the no-arg init()
?
Should I be taking a totally different approach?
question from:
https://stackoverflow.com/questions/65942698/calling-a-function-with-a-generic-parameter-requires-a-no-arg-init-for-the-type