У меня есть класс NetworkProvider
, который обрабатывает мои сетевые запросы и создается с помощью associatedtype
протокола TargetType
, который определяет, что необходимо для конечной точки.
Сейчас я использую NetworkProvider следующим образом:
let provider = NetworkProvider<IMDBAPI>()
provider.request<[Movie]>(IMDBAPI.getTop250Movies){
//When successful returns HTTPResponse.success([Movie])
}
Сейчас request<T: Decodable>
должен ссылаться на декодируемую модель. Однако я хотел бы иметь возможность сделать вывод из IMDBAPI.getTop250Movies
, поскольку он всегда будет возвращать массив объектов Movie
, поэтому кажется неэффективным требовать от разработчика предварительного знания того, что является типом возврата конечной точки до его использования.
Можно ли вывести модель, возвращаемую Endpoint / TargetType, через переданный ей протокол ассоциированного типа?
Код
TargetType
public protocol TargetType {
var baseURL: URL { get }
var path: String { get }
var method: HTTPMethod { get }
var headers: [String: String]? { get }
var task: HTTPRequestTask { get }
//var returnType: Decodable? { get } //This is what I'd like to use.
}
NetworkProvider
public protocol NetworkProviderType {
associatedtype Target: TargetType
}
public class NetworkProvider<Target: TargetType>: KindredProviderType {
public func request<T: Decodable>(_ target: Target, handler: @escaping (HTTPResponse<T>) -> ()) {
let endpoint = NetworkProvider.defaultEndpointMapping(for: target)
guard let urlRequest = try? endpoint.urlRequest() else {
return handler(HTTPResponse.error(HTTPError.failedToCreate(url: endpoint.url)))
}
session.runDataTask(with: urlRequest, completionHandler: { (data, response, error) in
let result = HTTPResponse<T>.createFrom(url: urlRequest.url!, error: error, data: data, response: response)
if case let HTTPResponse.error(error) = result {
loggingPrint(error)
}
handler(result)
})
}
}
Пример реализации TargetType
enum SplunkService {
case recordLogin(report: SplunkJourneyReporting)
case recordGameLaunch(report: SplunkJourneyReporting)
case recordError(report: SplunkEventReport)
}
extension SplunkService: TargetType {
var task: HTTPRequestTask {
switch self {
case .recordError(let report):
return HTTPRequestTask.requestBodyParameters(report.toDictionary())
case .recordGameLaunch(let report), .recordLogin(let report):
return HTTPRequestTask.requestBodyParameters(report.toDictionary())
}
}
var baseURL: URL { return URL(string: "https://api.unibet.com")! }
var path: String {
switch self {
case .recordLogin(_):
return "/eum-collector/journeys/login/reports"
case .recordGameLaunch(_):
return "/eum-collector/journeys/game_launch/reports"
case .recordError(_):
return "/eum-collector/events"
}
}
var method: HTTPMethod {
return .post
}
var headers: [String: String]? {
return [HTTPHeaderField.contentType.rawValue: "application/json"]
}
}