简体   繁体   English

在Swift中使用可编码扩展更新对象属性

[英]Updating object properties with codable extension in Swift

let me start by saying that I have already implemented Decodable which decodes JSON into several objects with these two Integer values: 首先让我说我已经实现了Decodable,它使用这两个Integer值将JSON解码为多个对象:

public class ARBufferData: DecoderUpdatable {

    private var previousStation: Int
    private var numberOfElements: Int

    func update(from decoder: Decoder) throws {
    //Still needs work
    }
}

What I am now trying to achieve is making the created objects updatable so that when a value in the JSON changes (eg numberOfElements) only the value is changed in the corresponding object. 我现在想要实现的是使创建的对象可更新,以便当JSON中的值更改(例如numberOfElements)时,仅在相应对象中更改该值。 I believe this guide can enable me to do it, but I am having trouble implementing it: Understanding and Extending Swift 4's Codable 我相信本指南可以让我这样做,但我无法实现它: 理解和扩展Swift 4的Codable

This is the extension of KeyedDecodingContainer: 这是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)
    }
}

The reason this would be helpful is that I can then set a property observer on that value and trigger a redraw of the visualisation. 这将有用的原因是我可以在该值上设置属性观察器并触发可视化的重绘。

I would be very grateful, if anyone can help or point me in the right direction. 如果有人能帮助或指出我正确的方向,我将非常感激。

Thank you! 谢谢!

Cheers 干杯

There are two ways to update the class. 有两种方法可以更新课程。 One, you decode each int by itself and compare. 一,你自己解码每个int并进行比较。 Two, you implement DecoderUpdatable for Int and call container.update with them as argument. 二,为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
    }
}

I do not know whether the blogpost-writer intended it this way though. 我不知道博客作者是否也这样想。 If he did, then generating the DecoderUpdatable conformances for the basic types could be a use case for Sourcery, but that's off topic here. 如果他这样做,那么为基本类型生成DecoderUpdatable一致性可能是Sourcery的一个用例,但这不是主题。

In Swift4 there is an interesting way to observe which you may also be interested in: 在Swift4中,有一种有趣的方式可以观察到您可能感兴趣的内容:

let token = buffer.observe(\.numberOfElements, options: [.new, .old]) {
    object, change in
    if change.oldValue != change.newValue {
        // Act on change of buffer.numberOfElements.
    }
}

Source 资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM