I have a Decodable
to which I want to add one extra property, not present in the plist.
The code below seems to work. I'm not sure why, since it no longer conforms to the plist. Can anyone explain?
Is there any better of doing it without having to write a custom init
and CodingKeys
?
struct Phrases: Decodable {
let animal: Dictionary<String, String>
let clothes: Dictionary<String, String>
let food: Dictionary<String, String>
let color: Dictionary<String, String>
}
extension Phrases {
var nouns: Dictionary<String, String> {
var nouns = [String: String]()
nouns = self.animal
nouns = self.clothes
nouns = self.food
return nouns
}
}
extension Dictionary {
static func = (left: inout Dictionary, right: Dictionary) {
left.merge(right) { $1 }
}
}
CodePudding user response:
This new property that you have added is a computed property, not a stored property like animal
, food
, etc
The synthesised Decodable
implementation is only derived from the stored properties of the struct, so adding a computed property does not change the synthesised Decodable
implementation at all.
This is because the semantics of computed property is that its value is computed every time you access it (call its getter). Every time you say nouns
, the code in the body runs, creating a new dictionary by computing the merge of the two dictionaries. This is as if it were just a function:
func nouns() -> Dictionary<String, String> {
var nouns = [String: String]()
nouns = self.animal
nouns = self.clothes
nouns = self.food
return nouns
}
If that is the semantics you want, then doing this is not problematic at all.
Alternatively, if you want the semantics of a stored property, you can add CodingKeys
(but no need for a custom init(from:)
) and use a lazy var:
lazy var nouns: [String: String] = {
...
}()
enum CodingKeys: CodingKey {
case animal, food, color, clothes
}
However, this makes nouns
mutable, which may not be desirable. To make nouns
a stored property and a let
, I'm pretty sure you have to write a custom init(from:)
.
See more differences between this and a computed property in my answer here.