skip to Main Content

I have a protocol called Endpoint

public protocol Endpoint {
    associatedtype ModelType: Codable

    var path: String { get }
    var method: HTTPMethod { get }
    var headers: [String: String] { get }
    var parameters: Parameters? { get set }
    var customTimeout: TimeInterval? { get }
}

I then have a few endpoints conforming to that protocol.

struct CurrenciesEndpoint: Endpoint { /* ... */ }

struct UserEndpoint: Endpoint { /* ... */ }

struct BalanceEndpoint: Endpoint { /* ... */ }

I want to fetch these endpoints in a DispatchGroup and once I get all the data from them I will create another object encapsulating all their responses. Like this

class DashboardResponseModel {
    public var currency: CurrencyResponse?
    public var user: UserResponse?
    public var balance: BalanceResponse?
}

I wanted to create a structure like this

struct EndpointMapping<T: Endpoint> {
    let endpoint: T
    let keyPath: WritableKeyPath<DashboardResponseModel, T.ModelType?>
}

Then in my fetch() method I wanted to create an array of EndpointMapping for each endpoint.

var endpointMappings: [EndpointMapping] = []
    EndpointMapping(endpoint: CurrenciesEndpoint(), keyPath: . currency),
    EndpointMapping(endpoint: UserEndpoint(), keyPath: . user),
    EndpointMapping(endpoint: BalanceEndpoint(), keyPath: . balance),
]

I am forced to give a type to array description but I need that array to be any type of Endpoint.

How can I fix this issue?

2

Answers


  1. You need get rid from associatedtype in protocol and from keypath in EndpointMapping.

    public protocol Endpoint {
        var path: String { get }
        var method: HTTPMethod { get }
        var headers: [String: String] { get }
        var parameters: Parameters? { get set }
        var customTimeout: TimeInterval? { get }
    }
    
    struct EndpointMapping {
        let endpoint: Endpoint
        let dataAcceptor: (Data) throws -> Void
    }
    
    extension DashboardResponseModel {
        func getDataAcceptor<T>(by keyPath: WritableKeyPath<DashboardResponseModel, T>) -> (Data) throws -> Void {
        {
            self[keyPath: keyPath] = try JSONDecoder().decode(T.self, from: data)
        }
    }
    
    Login or Signup to reply.
  2. As I understand, you want to store different kinds of EndpointMapping in one array. To do this you need to declare an intermediate protocol and use it in the array declaration with keyword any. Like this:

    protocol EndpointMappingProtocol {
        associatedtype Endpoint
        var endpoint: Endpoint { get }
    }
    
    struct EndpointMapping<T: Endpoint>: EndpointMappingProtocol {
        let endpoint: T
    }
    
    var endpointMappings: [any EndpointMappingProtocol] = [
        EndpointMapping(endpoint: CurrenciesEndpoint()),
        EndpointMapping(endpoint: UserEndpoint()),
        EndpointMapping(endpoint: BalanceEndpoint()),
    ]
    

    I removed the keyPath argument for clarity.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search