我可以使用willSet构建类实例字典条目吗?

时间:2018-03-28 01:39:33

标签: swift class constructor

我正在使用xCode 9.2,Swift 4.1

鉴于这两个简化的课程,目前有效:

class Prop : Codable {
    var origin:String?
    var result:String?

    init(_ origin:String) {
        self.origin = origin
    }
}

class PropList : Codable {
    var properties = [String: Prop]()

    func set (property:String, origin:String) {
        if properties[property] == nil {
            properties[property] = Prop(origin) //Create the entry
        } else {
            properties[property]!.origin = origin  //Update the entry
        }
    }
}

有没有办法使用willSet为字典条目创建Prop类的实例(如果它尚不存在)?我试图对此进行编码,但传递给willSet的newValue实际上是一个完整的字典。我想这假设有几个条目可能会同时发生变化,我认为实际上并不存在。这就是为什么下面的部分解决方案会迭代它。

想要使用willSet的原因是我可以使用普通语法,而不是使用特殊方法调用。使用上面的代码,我称之为:

var pl:PropList = PropList()
pl.set(property: "My Key", origin: "My Origin")
print(pl.properties["My Key"]?.origin as Any)

但我希望能够做到这一点:

var pl2:PropList = PropList()
pl2.properties["My Key"]?.origin = "My Origin"
print(pl2.properties["My Key"]?.origin as Any)
     

导致没有存储任何内容,或者:

var pl2:PropList = PropList()
pl2.properties["My Key"]!.origin = "My Origin"
print(pl2.properties["My Key"]?.origin as Any)
     

会引发运行时错误。

我认为这应该有效:

class PropList {
    var properties = [String: Prop]() {
        willSet {
            for e in newValue {
                if properties[e.key] == nil {
                    properties[e.key] = Prop()
                }
            }
        }
    }
}

但是Swift在打电话之前无法解决目标。

有什么方法吗?

1 个答案:

答案 0 :(得分:1)

您可以使用自定义下标很好地建模:

class Prop: Codable {
    var origin: String?
    var result: String?

    init(_ origin: String) {
        self.origin = origin
    }
}

class PropList: Codable {
    private var properties = [String: Prop]()

    public subscript(_ property: String) -> String? {
        get { return properties[property]?.origin }
        set {
            guard let unwrappedNewValue = newValue else {
                fatalError("Handle me properly!")
            }
            if let existingProperty = properties[property] {
                existingProperty.origin = unwrappedNewValue
                properties[property] = existingProperty
            } else {
                properties[property] = Prop(unwrappedNewValue)
            }
        }
    }
}

var propList = PropList()
propList["Some property"] = "Something called an 'origin' that needs to be better named/documented"