【发布时间】:2019-12-16 09:10:45
【问题描述】:
我正在尝试使用UserDefaults 保存配置数据结构,因此数据结构需要符合Codable 协议。这是我的数据结构:
// Data structure which saves two objects, which conform to the Connection protocol
struct Configuration {
var from: Connection
var to: Connection
}
protocol Connection: Codable {
var path: String { get set }
}
// Two implementations of the Connection protocol
struct SFTPConnection: Connection, Codable {
var path: String
var user: String
var sshKey: String
}
struct FTPConnection: Connection, Codable {
var path: String
var user: String
var password: String
}
如果我只是将Codable 添加到Configuration,它将无法正常工作。所以我必须自己实现。
extension Configuration: Codable {
enum CodingKeys: String, CodingKey {
case from, to
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let from = try container.decode(Connection.self, forKey: .from)
let to = try container.decode(Connection.self, forKey: .to)
self.from = from
self.to = to
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(from, forKey: .from)
try container.encode(to, forKey: .to)
}
}
对于decode() 或encode() 的每次调用,我都会收到错误Protocol type 'Connection' cannot conform to 'Decodable/Encodable' because only concrete types can conform to protocols。
我可以看到编译器很难识别,应该使用哪个类来解码给定的对象。但我认为对对象进行编码应该很容易,因为Connection 类型的每个对象都实现了encode() 方法。
我知道,问题出在协议上,该协议不能与Decodable/Encodable 一起使用。我将如何更改decode/encode 中的代码,以便我仍然可以将协议与各种实现一起使用?我的猜测是以某种方式告诉decode/encode 使用哪个协议实现。我会很感激这个问题的任何优雅的解决方案!
【问题讨论】:
-
错误是对的:
Codable需要符合Codable的具体类。除了泛型之外没有其他解决方法,它实际上在代码执行时提供了一个具体的类型。 -
谢谢,你能用泛型更详细地解释一下这个想法吗?
-
见杰里米的回答。这正是我的意思
-
我假设问题中有一个错字:协议定义为
Connection,但在扩展中,它被称为ConnectionConfiguration -
谢谢,当我尝试简化问题代码时会发生这种情况......
标签: swift encoding protocols decode codable