我们刚刚切换到swift 4.1,我们在Arrays的类型一致性方面遇到了一些困难。这是旧的方式:
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中工作。
答案 0 :(得分: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能够动态查询条件一致性支持来解决这个问题。