bakshioye
(Shubham Bakshi)
1
When I am declaring the Array variable as let it works just fine, but when I change the declaration from let to var, instead of taking the default value that is provided(an empty array), it initialises it as nil
import Foundation
struct Model: Codable {
let name: String? = "John"
let data: [String]? = []
}
let data = """
{
"name": "John"
}
""".data(using: .utf8)!
if let myObject = try? JSONDecoder().decode(Model.self, from: data) {
dump(myObject)
}
Output
▿ __lldb_expr_130.Model
▿ name: Optional("John")
some: "John"
▿ data: Optional([ ])
some: 0 elements
But when I change
let data: [String]? = [ ]
to
var data: [String]? = [ ]
the output changes to
▿ __lldb_expr_132.Model
▿ name: Optional("John")
some: "John"
data: nil
Hello,
This is because Codable does not decode initialized let properties:
import Foundation
struct Model: Codable {
let name: String? = "John"
let data: [String]? = []
}
let data = """
{
"name": "Michelle"
}
""".data(using: .utf8)!
if let myObject = try? JSONDecoder().decode(Model.self, from: data) {
dump(myObject)
}
Output (see how "Michelle" was discarded):
▿ __lldb_expr_3.Model
▿ name: Optional("John")
- some: "John"
▿ data: Optional([])
- some: 0 elements
When the let properties are not initialized, Codable does what you expect:
struct Model: Codable {
let name: String?
let data: [String]?
}
let data = """
{
"name": "Michelle"
}
""".data(using: .utf8)!
if let myObject = try? JSONDecoder().decode(Model.self, from: data) {
dump(myObject)
}
Output:
▿ __lldb_expr_6.Model
▿ name: Optional("Michelle")
- some: "Michelle"
- data: nil
2 Likes
More on initialized let properties: compare our code above with:
import Foundation
struct Model: Codable {
let name: String? = "John"
let data: [String]? = []
// Compiler error:
// Immutable value 'self.name' may only be initialized once
// Immutable value 'self.data' may only be initialized once
init(name: String?, data: [String]?) {
self.name = name
self.data = data
}
}
Some will advise you to generally prefer var declarations of struct properties, and to rely on variable declarations in order to be guaranteed with immutability:
struct Model {
var name: String? = "John"
var data: [String]? = []
}
// Immutable name and data
let model: Model = ...
You also have private(set) and other language niceties to control mutability.
So... let properties have their use cases, but they can come in the way, as you can see. Maybe consider using them only as a last resort. YMMV.
1 Like