How to implement to a generic protocol, which has a function using the Type of associatedtype?

Yiming Dong

I am creating some class confirms to a generic protocol, this generic protocol has a method which accept a parameter of the Type of the associatedtype, I use Xcode to generate the stub for me:


import UIKit

struct SomeObject: Codable {
    var id: String?
    var name: String?
}

protocol INetworkManager {
    associatedtype ResponseObject
    func get(url: String, ofType: ResponseObject.Type, completion: (ResponseObject?, Error?) -> Void)
}

class NetworkManager: INetworkManager {
    typealias ResponseObject = Codable

    func get(url: String, ofType: ResponseObject.Protocol, completion: (ResponseObject?, Error?) -> Void) {
        completion(SomeObject(id: "1", name: "hello"), nil)
    }
}

Instead of ResponseObject.Type it generates ResponseObject.Protocol for me, I don't actually know what this ResponseObject.Protocol is, and I can not pass SomeObject.self as the parameter like this:

let networkManager = NetworkManager()
networkManager.get(url: "http://whatever.com", ofType: SomeObject.self) { (responseObject, error) in
    print("got response object named: \(responseObject.name)")
}

compiler gave me this error:

error: Cannot convert value of type 'SomeObject.Type' to expected argument type 'NetworkManager.ResponseObject.Protocol' (aka '(Decodable & Encodable).Protocol')

I think something wrong with my implementation, anyone can give me any ideas?

Thanks!

Rob Napier

This isn't how associated types work. get should be generic over its response type, but the network manager itself isn't generic over some specific response type. I believe what you meant to here is this:

protocol NetworkManager {
    func get<ResponseObject>(url: String, 
                             ofType: ResponseObject.Type, 
                             completion: (Result<ResponseObject, Error>) -> Void) 
    where ResponseObject: Decodable
}

class TrivialNetworkManager: NetworkManager {
    func get<ResponseObject>(url: String, 
                             ofType: ResponseObject.Type, 
                             completion: (Result<ResponseObject, Error>) -> Void) 
    where ResponseObject: Decodable {
        completion(.success(SomeObject(id: "1", name: "hello"))
    }
}

For a more worked-out version of this specific problem you can read my protocol series, but the important concept here is that NetworkManager doesn't vary over its ResponseType, so there's no reason to make its ResponseType an associated type.

What you wrote is trying to say "some network managers will have a Codable ResponseType, and other network managers will have some other kind of ResponseType." Not "some other specific response type (like User)" but "some other protocol that its response types would have to conform to." While it's conceivable to build something like that, it's much more complex, and you'd need to explain your precise use case in order to design it. Specifically, you'd need to show several concrete implementations of your protocol in order to see what kind of shared code you're trying to extract.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to write generic function in Swift using a protocol associatedtype

Using associatedtype in a delegate protocol for a generic type

How to check the concrete type of associatedtype of a protocol inside generic class?

Infer generic from any using protocol with associatedtype

How to require a generic type implement a generic protocol using a specific type in the protocol

Implement generic protocol which already has a default implementation?

How to make extension to protocol using associatedtype and array

Use Protocol with associatedtype as a Type

Difference between using Generic and Protocol as type parameters, what are the pros and cons of implement them in a function

How to create a protocol with a generic function extending type

Swift protocol with associatedtype as a parameter type

how to use Void type in a closure of protocol with associatedtype in Swift

How to implement a protocol which has same name as another class

Protocol can only be used as a generic constraint because it has Self or associatedType requirements

Swift protocol with associatedtype (ambiguous for type lookup)

return View in swift protocol function with associatedtype

Protocol associatedType and <>

Swift Generic struct conform to protocol with associatedType got "Cannot convert return expression of type 'String' to return type 'Key'" Error

Implement delegate using generic protocol in Swift

How to initialize generic enum using a protocol with associated type?

Is there information somewhere on Swift protocol associatedtype using `=` versus `:`?

Variable that conforms to a protocol that has a generic function

How to implement a trait function generic over return type

How to describe constraint using conditional type which is based on generic type?

Using a Generic Type with a Protocol and associated type?

swift how to determine associatedtype in sub protocol

Cannot assign Generic value to protocol associatedType variable in an extension

Swift generics: how to match associatedtype with generic parameter

How to typecheck a generic function using a value of that same generic type in Flow