【问题标题】:Swift 4.1 array protocol conformanceSwift 4.1 数组协议一致性
【发布时间】:2018-04-02 16:48:06
【问题描述】:

我们刚刚切换到 swift 4.1,我们在数组的类型一致性方面遇到了一些困难。这是旧方法:

public typealias XDRCodable = XDREncodable & XDRDecodable

public protocol XDREncodable: Encodable {
    func xdrEncode(to encoder: XDREncoder) throws
}

public protocol XDRDecodable: Decodable {
    init(fromBinary decoder: XDRDecoder) throws
    init(fromBinary decoder: XDRDecoder, count: Int) throws
}

extension Array: XDRCodable {
    public func xdrEncode(to encoder: XDREncoder) throws {
        try encoder.encode(UInt32(self.count))
        for element in self {
            try (element as! Encodable).encode(to: encoder)
        }
    }

    public init(fromBinary decoder: XDRDecoder) throws {
        guard let binaryElement = Element.self as? Decodable.Type else {
            throw XDRDecoder.Error.typeNotConformingToDecodable(Element.self)
        }

        let count = try decoder.decode(UInt32.self)
        self.init()
        self.reserveCapacity(Int(count))
        for _ in 0 ..< count {
            let decoded = try binaryElement.init(from: decoder)
            self.append(decoded as! Element)
        }
    }
}

这在 swift 4.1 中会出现以下错误:

'XDRDecodable' 要求 'Element' 符合 'Decodable'

所以我们尝试将声明更改为:

extension Array: XDRCodable where Element : XDRCodable

虽然编译它仍然无法对数组进行编码并生成以下警告:

警告:Swift 运行时还不支持动态查询条件一致性('Swift.Array': 'stellarsdk.XDREncodable')

我看到这是一个work in progress,但是在正确实现类型一致性之前,是否有人有解决方法。我希望它现在可以像在 swift 4.0 中一样工作。

【问题讨论】:

    标签: ios generics types swift4 swift4.1


    【解决方案1】:

    我对 BinaryCoder 有类似的问题并创建了解决方法。但是您必须有权访问编码器和解码器实现。

    protocol XDRCodableArray {
        func binaryEncode(to encoder: XDREncoder) throws
        init(fromBinary decoder: XDRDecoder) throws
    }
    
    extension Array: XDRCodableArray {
       //copy implementation of XDRCodable from Array: XDRCodable
    }
    
    //delete extension Array: XDRCodable
    

    在解码中追加数组的特殊实现:

    ...
    case let binaryT as BinaryDecodable.Type:
        return try binaryT.init(fromBinary: self) as! T
    //new case
    case let array as BinaryCodableArray.Type:
        return try array.init(fromBinary: self) as! T
    ...     
    

    还有在编码中:

    ...
    case let binary as BinaryEncodable:
        try binary.binaryEncode(to: self)
    //new case    
    case let array as BinaryCodableArray:
        try array.binaryEncode(to: self)
    ...
    

    一般来说,条件协议一致性存在问题。您不能将变量转换为该协议(在某些情况下)。

    protocol Test: Codable {
        func test() -> String
    }
    
    extension Array: Test where Element: Codable {
        func test() -> String {
            return "Success"
        }
    }
    
    func doSomething(x: Codable) {
       let test = x as! Test
       test.test()
    }
    
    
    let array = ["value"]
    let t = (array as! Test).test   //success
    doSomething(x: array)   //fail on first row inside function
    

    我希望具有动态查询条件一致性支持的 Swift 4.2 能够解决这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-07
      • 2014-08-02
      相关资源
      最近更新 更多