我为 SwiftUI 编写了一段代码,根据
Shape
参数提供特定的 Enum
。不幸的是,一个看起来很自然的 switch
命令抱怨 Rectangle()
、Circle()
和 Diamond()
(我自己的 Shape
)的类型全部不匹配。
我怎样才能让 Xcode 相信所有这些都是
Shape
并且在进一步的代码中都完全符合 SwiftUI 修饰符?
演示问题的代码片段:
import SwiftUI
enum MaskShapes {
case rectangle, diamond, circle
}
struct ContentView: View {
var body: some View {
let shape = MaskShapes.diamond
let mask = switch shape {
case .rectangle: Rectangle() // Error: Branches have mismatching types 'Rectangle' and 'Circle'
case .diamond: Diamond() // Error: Branches have mismatching types 'ContentView.Diamond' and 'Circle'
case .circle: Circle()
}
Spacer()
VStack {
Image(systemName: "globe")
.imageScale(.large)
Text("Hello, world!")
}
.frame(width: 300, height: 200)
.background(mask.foregroundColor(.red))
Spacer()
}
struct Diamond: Shape {
func path(in rect: CGRect) -> Path {
var p = Path()
p.move(to: CGPoint(x: rect.midX, y: 0))
p.addLine(to: CGPoint(x: 0, y: rect.midY))
p.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
p.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
p.closeSubpath()
return p
}
}
}
#Preview {
ContentView()
}
如果 SwiftUI 支持
ShapeBuilder
属性,那就太好了。也许你可以自己写,但我不认为这会很容易。因此,这里有两种可能的解决方法:
1。创建
ViewBuilder
函数,创建指定的 Shape
我认为它还需要使用
if-else
而不是 switch
。
@ViewBuilder
func mask(shape: MaskShapes) -> some View {
if shape == .rectangle {
Rectangle()
} else if shape == .diamond {
Diamond()
} else {
Circle()
}
}
var body: some View {
let shape = MaskShapes.diamond
Spacer()
VStack {
Image(systemName: "globe")
.imageScale(.large)
Text("Hello, world!")
}
.frame(width: 300, height: 200)
.background(mask(shape: shape).foregroundColor(.red))
Spacer()
}
2。将
Shape
提供给通用函数
此方法保留了
Shape
类型,因此如果您想使用特定于形状的修改器,那么您可以:
@ViewBuilder
func bodyWithShapedBackground<S: Shape>(shape: S) -> some View {
Spacer()
VStack {
Image(systemName: "globe")
.imageScale(.large)
Text("Hello, world!")
}
.frame(width: 300, height: 200)
.background(shape.foregroundColor(.red))
Spacer()
}
var body: some View {
let shape = MaskShapes.diamond
if shape == .rectangle {
bodyWithShapedBackground(shape: Rectangle())
} else if shape == .diamond {
bodyWithShapedBackground(shape: Diamond())
} else {
bodyWithShapedBackground(shape: Circle())
}
}