在 SwiftUI 中使用泛型作为函数属性的默认值

Posted

技术标签:

【中文标题】在 SwiftUI 中使用泛型作为函数属性的默认值【英文标题】:Using Generics as Default Values for Function Properties in SwiftUI 【发布时间】:2020-06-15 05:57:17 【问题描述】:

我正在尝试扩展 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' 类型的默认参数值无法转换为类型 '背景' "插入'为!背景'

“颜色”类型的默认参数值无法转换为“S”类型 "插入'为!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)

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

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

以上是关于在 SwiftUI 中使用泛型作为函数属性的默认值的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin泛型 ① ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 )

在 SwiftUI Picker 中为 NSManagedObject 设置默认值?

关于泛型

泛型谓词的默认值作为参数

对泛型的理解

关于泛型的知识