我正在尝试创建一个服务类,该服务类也具有相应api的解码类类型
import UIKit
struct LoginResponse: Codable {
var action: String
var result: String
var key: String
}
struct LogoutResponse: Codable {
var action: String
var result: String
}
enum Api {
case login
case logout
var backingType: Codable {
switch self {
case .login:
return LoginResponse.self as! Codable
case .logout:
return LogoutResponse.self as! Codable
}
}
}
let loginResponse = LoginResponse(action: "login", result: "result", key: "key")
let loginData = try! JSONEncoder().encode(loginResponse)
let decodedData = try! JSONDecoder().decode(Api.login.backingType, from: loginData)
得到的错误是->
**不能转换"可编码"类型的值。输入'(又名'(可解码&可编码).Type')到预期的参数类型'T.Type'
无法推断泛型参数'T'。**
我也试过使用泛型
import UIKit
struct LoginResponse: Codable {
var action: String
var result: String
var key: String
}
struct LogoutResponse: Codable {
var action: String
var result: String
}
enum Api<T: Codable> {
case login
case logout
var backingType: Codable.Type {
switch self {
case .login:
return LoginResponse.self
case .logout:
return LogoutResponse.self
}
}
var genericBackingType: T.Type {
switch self {
case .login:
return LoginResponse.self as! T.Type
case .logout:
return LogoutResponse.self as! T.Type
}
}
}
let loginResponse = LoginResponse(action: "login", result: "result", key: "key")
let loginData = try! JSONEncoder().encode(loginResponse)
let decodedData = try! JSONDecoder().decode(Api.login.backingType as! Codable.Type, from: loginData)
请给我指一个合适的方向
在两次尝试中,要解码的类型必须是具体类型,不能是协议。
在这种情况下,最合适的解决方案是带有关联类型
的enum。enum Api : Decodable {
case login(LoginResponse)
case logout(LogoutResponse)
private enum CodingKeys : String, CodingKey { case action, result, key }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let action = try container.decode(String.self, forKey: .action)
let result = try container.decode(String.self, forKey: .result)
switch action {
case "login":
let key = try container.decode(String.self, forKey: .key)
self = .login(LoginResponse(action: action, result: result, key: key))
case "logout":
self = .logout(LogoutResponse(action: action, result: result))
default : throw DecodingError.dataCorruptedError(forKey: .action, in: container, debugDescription: "Invalid action: (action)")
}
}
}
它解码action
密钥,并根据值返回具有相关响应类型的适当大小写。
结构可以是相同的,如果在实际生活中这些结构永远不会被编码,您甚至可以省略action
成员。如果是这样,您可以进一步省略LogoutResponse
结构体,并在logout
的情况下对result
使用相关的String
类型。
struct LoginResponse : Codable {
let action: String
let result: String
let key: String
}
struct LogoutResponse : Codable {
let action: String
let result: String
}
解码的方法是
let loginResponse = LoginResponse(action: "login", result: "result", key: "key")
let loginData = try! JSONEncoder().encode(loginResponse)
let decodedApi = try! JSONDecoder().decode(Api.self, from: loginData)
switch decodedApi {
case .login(let response): print(response)
case .logout(let response): print(response)
}