gpt4 book ai didi

swift - 如何引用作为关联类型的协议(protocol)的属性?

转载 作者:行者123 更新时间:2023-11-28 13:40:58 24 4
gpt4 key购买 nike

我有一个 NetworkProvider处理我的网络请求并使用 associatedtype 实例化的类的 TargetType定义端点所需内容的协议(protocol)。

现在我使用 NetworkProvider 如下:

let provider = NetworkProvider<IMDBAPI>()
provider.request<[Movie]>(IMDBAPI.getTop250Movies){
//When successful returns HTTPResponse.success([Movie])
}

现在 request<T: Decodable>必须引用可解码模型。但是我希望能够从 IMDBAPI.getTop250Movies 中推断出这一点因为这将始终返回 Movie 的数组对象,因此要求开发人员在使用端点之前提前了解端点的返回类型似乎适得其反。

是否可以通过传递给端点/目标类型的关联类型协议(protocol)推断出端点/目标类型返回的模型?


代码

目标类型

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.
}

网络提供者

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"]
}
}

最佳答案

希望对您有所帮助。请查看以下与我附加的代码内联的评论...

// the compiler understand exactly what type `T` is because we `init` the class using `T` and that is also the same type used to conform to `TargetType`, in other words if I do `NetworkProvider(returnType: decodableThing)`, the compiler knows that `T` = (the class of `decodableThing`)
import UIKit
import Foundation

public protocol TargetType {

associatedtype ReturnTypeUsed: Decodable

var returnType: ReturnTypeUsed? { get } //This is what I'd like to use.
}

public class NetworkProvider<T> {

// The compiler understand exactly what type `T` is because we `init` the class using `T` and that is also the same type used to conform to `TargetType`
// in other words if I do `NetworkProvider(returnType: decodableThing)`, the compiler knows that `T` = (the class of `decodableThing`)
public typealias ReturnTypeUsed = T

public var returnType: T?

init(returnType: T) {
self.returnType = returnType
}

}

class Movie: Decodable {

}

let someMovie = Movie()

class IMDBAPI: TargetType {

var returnType: Movie?

}

let networkProvider = NetworkProvider(returnType: someMovie)

print(networkProvider.returnType) // returns `Optional(__lldb_expr_5.Movie)

关于swift - 如何引用作为关联类型的协议(protocol)的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56037455/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com