简体   繁体   English

SwiftUI generics 从第二个初始化程序使用

[英]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).我希望以与 Apple 的某些实现(例如按钮)类似的方式构建 SwiftUI 组件。 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).我希望有一个 label 与该组件相关联(这只是另一个视图),或者能够仅使用字符串进行构造(并且默认使用文本视图)。

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 .如果您希望这是默认设置,那么您需要确保它仅适用于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上添加约束:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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