条件协议符合性:无法将类型'Array <_>'的值转换为指定类型'[UInt8]'

时间:2018-08-23 03:26:30

标签: swift swift-protocols swift4.1

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

任何帮助将不胜感激。

2 个答案:

答案 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);