条件协议一致性:无法将类型"数组"<_>"的值转换为指定类型"[UInt8]"



尝试使用条件一致性在 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);

最新更新