简体   繁体   中英

SwiftUI generics used from second initialiser

I am looking to structure a SwiftUI component in a similar way as some of Apple's implementations (Eg Button). I am looking to have a label associated to this component (which is just another View) or have the ability to construct using just a string (and default to using a Text view).

This is what I have:

struct ExampleComponent<Label> : View where Label : View {
    let label: () -> Label
    let action: () -> ()
    
    init(_ title: String, action: @escaping () -> ()) {
        self.init(label: {
            Text(title)
        }, action: action)
    }
    
    init(@ViewBuilder label: @escaping () -> Label, action: @escaping () -> ()) {
        self.label = label
        self.action = action
    }
    
    var body: some View {
        label()
    }
}

However, this cannot compile due to the error:

Cannot convert value of type 'Text' to closure result type 'Label'.

What's going wrong?

If you want this to be a default, then you need to make sure it only applies in cases where Label == Text . In other situations, you can't use it. I generally do this with a constrained extension:

extension ExampleComponent where Label == Text {
    init(_ title: String, action: @escaping () -> ()) {
        self.init(label: {
            Text(title)
        }, action: action)
    }
}

But you can also add the constraint on the init directly:

init(_ title: String, action: @escaping () -> ()) where Label == Text {
    self.init(label: {
        Text(title)
    }, action: action)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM