尝试使用条件一致性在 Swift 4.1 中扩展数组、字符串和字典,但在尝试初始化具有符合Decodable
/Encodable
的数组时遇到了死胡同,该Element
数组通过称为BinaryCodable
的自定义协议符合/。
以下摘录来自 https://github.com/mikeash/BinaryCoder,但已调整为 使用 Swift 的新条件一致性,以便编译。
extension Array: BinaryCodable where Element: BinaryDecodable, Element: BinaryEncodable {
public func binaryEncode(to encoder: BinaryEncoder) throws {
try encoder.encode(self.count)
for element in self {
try element.encode(to: encoder)
}
}
public init(fromBinary decoder: BinaryDecoder) throws {
let binaryElement = Element.self
let count = try decoder.decode(Int.self)
self.init()
self.reserveCapacity(count)
for _ in 0 ..< count {
let decoded = try binaryElement.init(from: decoder)
self.append(decoded)
}
}
}
extension String: BinaryCodable {
public func binaryEncode(to encoder: BinaryEncoder) throws {
try (Array(self.utf8) as! BinaryCodable).binaryEncode(to: encoder)
}
public init(fromBinary decoder: BinaryDecoder) throws {
let utf8: [UInt8] = try Array(fromBinary: decoder)
if let str = String(bytes: utf8, encoding: .utf8) {
self = str
} else {
throw BinaryDecoder.Error.invalidUTF8(utf8)
}
}
}
但是,我得到:
无法将类型"数组<_>"的值转换为指定类型"[UInt8]">
对于此行:
let utf8: [UInt8] = try Array(fromBinary: decoder)
任何帮助将不胜感激。
为了使Array<UInt8>
被BinaryCodable
,它的元素类型UInt8
必须是BinaryCodable
,而事实并非如此。该协议具有 其所需方法的默认实现,但一致性必须 仍然明确声明:
extension UInt8: BinaryCodable {}
然后你的extension String
编译, 您甚至可以摆脱强制投as! BinaryCodable
编码方法(使用guard
允许保存一行(:
extension String: BinaryCodable {
public func binaryEncode(to encoder: BinaryEncoder) throws {
try Array(self.utf8).binaryEncode(to: encoder)
}
public init(fromBinary decoder: BinaryDecoder) throws {
let utf8: [UInt8] = try Array(fromBinary: decoder)
guard let str = String(bytes: utf8, encoding: .utf8) else {
throw BinaryDecoder.Error.invalidUTF8(utf8)
}
self = str
}
}
如果您希望数组的每个元素都有一个值,请将其更改为此值:
let utf8:Array<UInt8> = try Array(from: decoder);
如果您希望数组的某些元素具有 null 或空值,请将其更改为以下内容:
let utf8:Array<UInt8?> = try Array(from: decoder);