首页 > 解决方案 > 在 SwiftUI 中使用泛型作为函数属性的默认值

问题描述

我正在尝试扩展 SwiftUI View 协议以简化我的代码。我在“视图”上创建了一个函数来设置填充、背景、覆盖和阴影,而不必在整个项目中每次都编写所有这些修饰符。

@inlinable public func backgroundWithBorder<Background: Shape, S: ShapeStyle>(
                                                _ background: Background,
                                                fill: S,
                                                borderStyle: S,
                                                borderWidth: CGFloat = 2, 
                                                shadow: Bool = false) -> some View {

        self
            .padding()
            .background(background.fill(fill))
            .overlay(background.stroke(borderStyle, lineWidth: borderWidth))
            .shadow(color: shadow ? Color.primary.opacity(0.2) : Color.clear, radius: 20, x: 0, y: 0)

    }

上面的代码可以按需要工作,但是我想为“Background”和“S”泛型提供默认值,例如......

@inlinable public func backgroundWithBorder<Background: Shape, S: ShapeStyle>(
                                                    _ background: Background = Circle(),
                                                    fill: S = Color.blue,
                                                    borderStyle: S = Color.green,
                                                    borderWidth: CGFloat = 2, 
                                                    shadow: Bool = false) -> some View

注意:我使用的是泛型,因为我并不总是想要相同的形状,而且我想在某些情况下使用渐变填充。

当我添加这些默认值时,我得到了错误

'Circle' 类型的默认参数值无法转换为 'Background' 类型“插入 'as!Background'

'Color' 类型的默认参数值不能转换为 'S' 类型 "Insert ' as!S'

当我这样做时,错误会在扩展内消失

@inlinable public func backgroundWithBorder<Background: Shape, S: ShapeStyle>(
                                                _ background: Background = Circle() as! Background,
                                                fill: S = Color.blue as! S,
                                                borderStyle: S = Color.blue as! S,
                                                borderWidth: CGFloat = 2, 
                                                shadow: Bool = false) -> some View {

但是,在 ContentView 中,我收到错误消息...

VStack {
    Text("Hello")
    Text("World")
}
.backgroundWithBorder()

无法推断通用参数“背景”

无法推断通用参数“S”

同样,如果我提供值,而不是使用默认输入参数,它会构建并运行得非常好。

VStack {
    Text("Hello")
    Text("World")
}
.backgroundWithBorder(Circle(),
                      fill: Color.blue,
                      borderStyle: Color.green,
                      shadow: true)

总之,是否可以为这些泛型提供默认值,这样我就不会在我的代码中一遍又一遍地编写相同的值?

任何帮助,将不胜感激。

标签: swiftgenericsswiftui

解决方案


我发现使用泛型和使用默认值之间存在明显的矛盾。相反,为什么不创建一个为原始函数提供硬编码值的包装函数

@inlinable public func backgroundWithBorder() {
    self.backgroundWithBorder(Circle(), fill: Color.blue, borderStyle: Color.green)
}

推荐阅读