I write a code for SwiftUI that delivers a certain Shape
depending on an Enum
parameter. Unfortunately, a switch
command, which seems natural for the purpose, complains that Rectangle()
, Circle()
, and Diamond()
(my own Shape
) have all mismatching types.
How can I convince Xcode that all these are Shape
s and all perfectly comply with SwiftUI modifiers in further code?
The code snippet demonstrating the problem:
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()
}
2
Answers
What would be nice, would be if SwiftUI supported a
ShapeBuilder
attribute. Maybe you could write it yourself, but I don’t expect it will be easy. So here are two possible workarounds:1. Create a
ViewBuilder
function to create the specifiedShape
EDIT I thought
if-else
was needed here, but in fact aswitch
does work (thanks Rob Napier for the tip).2. Supply the
Shape
to a generic functionThis approach retains the
Shape
type, so if you wanted to use a modifier that was Shape-specific then you could.EDIT A
switch
works here too.By making your
shape
typed toAnyShape
you can make the other shapes also conform to it by wrapping them inAnyShape(*shape*)
for example:AnyShape(Rectangle())
So your switch becomes:
Making these changes will make it compile + work!