首先,我已经实现了Decodable,它使用以下两个Integer值将JSON解码为多个对象:
public class ARBufferData: DecoderUpdatable {
private var previousStation: Int
private var numberOfElements: Int
func update(from decoder: Decoder) throws {
//Still needs work
}
}
我现在想要实现的是使创建的对象可更新,以便当JSON中的值更改时(例如numberOfElements),只有相应对象中的值才会更改。我相信本指南可以使我做到这一点,但是我在实施它时遇到了麻烦:Understanding and Extending Swift 4’s Codable
这是KeyedDecodingContainer的扩展:
extension KeyedDecodingContainer {
func update<T: DecoderUpdatable>(_ value: inout T, forKey key: Key, userInfo: Any) throws {
let nestedDecoder = NestedDecoder(from: self, key: key)
try value.update(from: nestedDecoder)
}
}
之所以有用,是因为我可以在该值上设置一个属性观察器,并触发可视化的重新绘制。
如果有人能帮助我或指出正确的方向,我将不胜感激。
谢谢!
欢呼
答案 0 :(得分:1)
有两种更新类的方法。第一,您自己解码每个int并进行比较。第二,为Int实现DecoderUpdatable
并以它们作为参数调用container.update
。
public class ARBufferData: NSObject, Decodable, DecoderUpdatable {
init(previousStation: Int, numberOfElements: Int) {
self.previousStation = previousStation
self.numberOfElements = numberOfElements
}
@objc dynamic var previousStation: Int
@objc dynamic var numberOfElements: Int
private enum CodingKeys: String, CodingKey {
case previousStation, numberOfElements
}
public func update(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
try container.update(&previousStation, forKey: .previousStation)
try container.update(&numberOfElements, forKey: .numberOfElements)
}
}
extension Int: DecoderUpdatable {
public mutating func update(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let result = try container.decode(Int.self)
guard result != self else { return }
self = result
}
}
我不知道博客作者是否打算这样做。如果他这样做了,那么为基本类型生成DecoderUpdatable一致性可能是Sourcery的用例,但这不在本文的讨论范围。
在Swift4中,有一种有趣的观察方式,您可能也对此感兴趣:
let token = buffer.observe(\.numberOfElements, options: [.new, .old]) {
object, change in
if change.oldValue != change.newValue {
// Act on change of buffer.numberOfElements.
}
}