Callback block not work with complicate generic type


(Lee) #1

Hi all, I have a result handler like that:

public enum CoreLibResult<T> {
case success(T)
case fail(Error)
}

And I Have a class:

public typealias BaseCompletion<T: Codable> = (_ result: CoreLibResult<ZPConfigsResponse<T>>) -> Void
final class Handler<C: Codable> {
    var completion: BaseCompletion<C>?
    init(callBack: @escaping BaseCompletion<C>) {
        self.completion = callBack
    }
    func handlerResponse(data: Data, err: Error) {
        guard err == nil else {
            handlerError(err)
            return
        }
        do {
            let decoder = JSONDecoder()
            let configs = try decoder.decode(C.self, from: data)
            completion?(.success(configs))//Error: `Type of expression is ambiguous without more context`
            completion = nil
        } catch let err {
            handlerError(err)
        }
    }
    private func handlerError(_ error: Error) {
        DDLogDebug(error.localizedDescription)
        completion?(.fail(error))
        completion = nil
    }
}

I got the error Type of expression is ambiguous without more context when call completion?(.success(configs)).
What I am missing here?


(Tomáš Znamenáček) #2

The .success initializer expects an argument, in this case of type ZPConfigsResponse<T>. But you’re passing in configs, ie. C:

let configs = try decoder.decode(C.self, from: data)

C doesn’t appear to be compatible with ZPConfigsResponse<T>, hence the error. Did I get it right? The code is hard to read, it would be nice to simplify it somehow.


(Lee) #3

I change the typealias BaseCompletion to:
public typealias BaseCompletion<T: Codable> = (_ result: CoreLibResult<T>) -> ()
It can remove the above error but got another error when calling the method:

public typealias ConfigCompletion = (CoreLibResult<ZPConfigsResponse<String>>) -> ()
public func getRemoteConfigValue(for configName: String, userid: String, accessToken: String, callBack: @escaping ConfigCompletion) {
     self.remoteConfigService?.getValueForKey(configName, userID: userid, accessToken: accessToken, defaultParams: remoteConfigParams?.getDefaultParams().toString, responseHandler: ConfigCompletion)//Error:Cannot convert value of type 'ZPRemoteConfigManager.ConfigCompletion.Type' (aka '((CoreLibResult<ZPConfigsResponse<String>>) -> ()).Type') to expected argument type 'CorelibResponseHandlerProtocol?'
}

The error is: Cannot convert value of type 'ZPRemoteConfigManager.ConfigCompletion.Type' (aka '((CoreLibResult<ZPConfigsResponse<String>>) -> ()).Type') to expected argument type 'CorelibResponseHandlerProtocol?'
Sorry for complicated code of generic type. Because I don't want to duplicate code, so I try to use generic.
Edit: Sorry, my mistake. The right code must be:

public func getRemoteConfigValue(for configName: String, userid: String, accessToken: String, callBack: @escaping ConfigCompletion) {
        self.remoteConfigService?.getValueForKey(configName, userID: userid, accessToken: accessToken, defaultParams: remoteConfigParams?.getDefaultParams().toString, responseHandler: ResponseHandler<ZPConfigsResponse<String>>(callBack: callBack))
}