In SwiftUI, I'm trying to create a class that conforms Codable
(so I can save it in @AppStorage
), and has @Published
properties so it can be passed as an EnvironmentObject
.
This tutorial gave me the following example:
class User: ObservableObject, Codable {
enum CodingKeys: CodingKey {
case name
}
@Published var name = "Bob Smith"
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
}
func encode(to encoder: Encoder) throws {
...
}
}
I'm wondering how I would go about passing a String
into the class initializer. (i.e. var user = User("Bob Smith"
)
Unless I'm mistaken, required
means that all instances & subclasses must use that initializer. Given that name
is already being assigned in the existing initializer, how would I go about passing a custom name into the initializer of this class?
CodePudding user response:
Yes required
means that all subclasses must implement the init and in this case it's a requirement because of the conformance to Codable
.
But this doesn't mean you can't add other initialisers so that you can create instances of your class from other type of data than JSON
So simply add wathever init you need
init(name: String) {
self.name = name
}
let user = User(name: "Joe")
And for a sub class you must add an init(from:)
and you might add another custom init if you want to, here is an example
class SuperUser: User {
var likesBananas: Bool
enum CodingKeys: CodingKey {
case likesBananas
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
likesBananas = try container.decode(Bool.self, forKey: .likesBananas)
try super.init(from: decoder)
}
init(name: String, likesBananas: Bool) {
self.likesBananas = likesBananas
super.init(name: name)
}
override func encode(to encoder: Encoder) throws {...}
}