With this code:
public protocol LoginInfoBase: Decodable {
var access_token: String? { get }
var notifications: [PushNotification] { get }
}
public class ExampleLoginInfo: LoginInfoBase {
public var access_token: String? = nil
public var notifications: [PushNotification] = []
public var user_info: UserInfo? = nil
public var more_example_data: String? = nil
}
public func genericQuery<T: Decodable>(urlString: String, method: QueryType, params: Parameters?, decodable: T.Type,completionHandler: @escaping (Swift.Result<T, Error>) -> Void) {
<more code here>
}
}
public func getLoginInfo(loginInfoClass: LoginInfoBase.Type, completionHandler: @escaping (Swift.Result<LoginInfoBase, Error>) -> Void) {
genericQuery(urlString: "\(baseURL)/users/get_login_info/", method: .get, params: nil, decodable: loginInfoClass.self) { result in
<more code here>
}
}
I then call getLoginInfo
...
getLoginInfo(loginInfoClass: ExampleLoginInfo.self) { result in
<more code here>
}
...and get this error:
Generic parameter 'T' could not be inferred
Cannot convert value of type 'LoginInfoBase.Type' to expected argument type 'T.Type'
Here's the background. I'm trying to set up a generic login library that can be invoked with a class that contains user data that's specific to each app that it's used in. In this app I subclass LoginInfoBase
as ExampleLoginInfo
to add the extra user data. My intention is that library will then decode the user data returned from the server into ExampleLoginInfo.
Any ideas how to fix the error?
This is the wrong signature:
public func getLoginInfo(loginInfoClass: LoginInfoBase.Type, completionHandler: @escaping (Swift.Result<LoginInfoBase, Error>) -> Void)
You mean this:
public func getLoginInfo<T: LoginInfoBase>(loginInfoClass: T.Type, completionHandler: @escaping (Swift.Result<LoginInfoBase, Error>) -> Void)
^^^^^^^^^^^^^^^^^^ ^
You need to pass a concrete type to getLoginInfo
that conforms to LoginInfoBase. Not just any subtype. This matches your genericQuery
method.
You should then modify your call to genericQuery as:
genericQuery(urlString: "\(baseURL)/users/get_login_info/",
method: .get,
params: nil,
decodable: T.self) { ... } // use T.self here.
For more details, see Alexander's link.