2
votes

How can I create 2 initializers in a SwiftUI view (which is a struct)?

I am trying to make an initializer take takes a title and a color and one that only takes a title.

I have tried to create convenience initializers, but it seems that Swift will not allow this.

Are convenience initializers useful in SwiftUI Views?

2

2 Answers

4
votes

You can do it, like this way:

Convenience initializer are accessible in reference types! Not in value types (such as Struct)!


struct CustomView: View {

    let title: String
    let color: Color

    init(title: String, color: Color) {
        self.title = title
        self.color = color
    }
    
    init(title: String) {
        self.title = title
        self.color = Color.black
    }

    var body: some View {
        
        Text(title)
            .foregroundColor(color)
        
    }
    
}

use case:

struct ContentView: View {

    var body: some View {
        
        CustomView(title: "Hello")
        
        CustomView(title: "Hello", color: Color.red)
        
    }
}
2
votes
struct CustomView: View {
    var title: String
    var color: Color = .black
    
    var body: some View {
        Text(title)
            .foregroundColor(color)
    }
}

struct FooView: View {
    var body: some View {
        CustomView(title: "Title")
        CustomView(title: "Hello", color: .red)
    }
}

Swift synthesizes memberwise initializers by default. That means you get an initializer that accepts values for each of the struct’s properties for free. You don't have to write one manually. If any properties have default values, the generated initializer will use those as default values for the arguments.

If you want your own initializer and you want to keep the generated initializer, write your own one in an extension on the type.

Update: As pointed out by swiftPunk, this doesn't give you two init functions, so if you need to do that:

struct CustomView: View {
    let title: String
    var color: Color = .black
    
    var body: some View {
        Text(title)
            .foregroundColor(color)
    }
}

extension CustomView {
    init(title: String) {
        self.title = title
    }
}

Now you actually have two actual functions you can use if you need that (maybe you want to compose them or something)

let f1 = CustomView.init(title:)
let f2 = CustomView.init(title:color:)

You can make title let instead of var if you like, but view structs are always recomputed anyway.