I have a UIHostingController with two very similar initializers, just with different parameters. Here is a simplified example of what I'm trying to do:
public class ExampleViewController: UIHostingController<ExampleView> {
public let var1: Int
public let var2: String
public init(var1: Int, var2: String) {
self.var1 = var1
self.var2 = var2
super.init(rootView: ExampleView(var1, var2))
}
public convenience init(var1: Int) {
self.var1 = var1
self.var2 = “”
super.init(rootView: ExampleView(var1, ""))
}
}
Since my real use case is more complicated than this example, it would be great if I could reuse the shared logic in the initializers, something like this:
public class ExampleViewController: UIHostingController<ExampleView> {
public let var1: Int
public let var2: String
public init(var1: Int, var2: String) {
self.var1 = var1
self.var2 = var2
super.init(rootView: ExampleView(var1, var2))
}
public init(var1: Int) {
self.init(var1: var1, var2: "")
}
}
However, I am unable to reference self/self.init until all properties are set and super.init is called. Does this mean that I’m not able to reuse the initializer logic, or is there another way of doing this?
Your intuition is correct; deduplicating initialization logic is a good idea.
For it to work correctly, you need to mark you second initializer with
convenience:Usually these are the most clear when most initializers are just a customization/specialization implemented in terms of some other centralized initializer. A picture is worth a thousand words:
Ideally, you only have 1 designated initializer at each level, where possible.
However, in this case, you can just leverage Swift's ability to have default parameter values, and get away with just a single simple initializer:
This is likely just a toy example, but I'll caution anyway:
""is almost never an appropriate default value for strings (contrary to the defaults baked into other languages, like 0 values in Go or default-initialized values in Java).