如何在swift中返回解码可编码的类类型



我正在尝试创建一个服务类,该服务类也具有相应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)
}

相关内容

  • 没有找到相关文章

最新更新