尝试使用条件一致性在Swift 4.1中扩展数组,字符串和字典,但是在尝试使用符合Element
/ {的Decodable
s初始化数组时陷入僵局{1}}通过名为Encodable
的自定义协议。
以下摘录来自https://github.com/mikeash/BinaryCoder,但已对其进行了调整,以使用Swift的新条件一致性以便对其进行编译。
BinaryCodable
但是,我得到了:
无法将类型“ Array <_>”的值转换为指定的类型“ [UInt8]”
对于此行:
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)
}
}
}
任何帮助将不胜感激。
答案 0 :(得分:1)
为使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
}
}
答案 1 :(得分:0)
如果希望数组的每个元素都有一个值,请将其更改为该值:
let utf8:Array<UInt8> = try Array(from: decoder);
如果希望数组的某些元素具有空值或空值,请将其更改为此:
let utf8:Array<UInt8?> = try Array(from: decoder);