Dawy
Dawy

Reputation: 946

How to return different Views from switch case

I have this function in my SwiftUI code

func getShape(shape:Int, i: Int) -> some View {
    switch self.selectedShape {
    case 0:
        return Rectangle()
               .stroke(Color.pink)
               .frame(width: 150, height: 150)
               .position(CGPoint(x: scrCenterX, y: scrCenterY))
               .rotationEffect(Angle(degrees: Double(i) * Double(self.angleStep)))
    case 1:
        return Circle()
               .stroke(Color.pink)
               .frame(width: 150, height: 150)
               .position(CGPoint(x: scrCenterX, y: scrCenterY))
            .rotationEffect(Angle(degrees: Double(i) * Double(self.angleStep)))
    case 2:
        return Capsule()
               .stroke(Color.pink)
               .frame(width: 150, height: 150)
               .position(CGPoint(x: scrCenterX, y: scrCenterY))
            .rotationEffect(Angle(degrees: Double(i) * Double(self.angleStep)))
    default:
        return Rectangle()
        .stroke(Color.pink)
        .frame(width: 150, height: 150)
        .position(CGPoint(x: scrCenterX, y: scrCenterY))
            .rotationEffect(Angle(degrees: Double(i) * Double(self.angleStep)))
    }
}

and compliler says that "Function declares an opaque return type, but the return statements in its body do not have matching underlying types". If I change in all "cases" shape to e.g. Circle then code is compiled without any error. How I cold achieve returning shape based on selectedShape value? Thanks.

Upvotes: 3

Views: 1982

Answers (2)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119458

You need to use the @ViewBuilder on your function and drop the return keywords:

@ViewBuilder // 👈 Use this on the function
func getShape(shape:Int, i: Int) -> some View {
    switch self.selectedShape {
    case 0:
        Rectangle().frame(width: 50)
    case 1:
        Circle().stroke()
    default:
        Text("Any other view")
    }
}

Upvotes: 3

New Dev
New Dev

Reputation: 49590

some View is an Opaque (to the caller) return type that is some type that conforms to View. But it has to be a specific type known at compile-time to the callee.

So, at compile-time, you need to decide which concrete type conforming to View it's going to be. It cannot be either Rectangle or Circle; it always needs to be the same type. So what you're trying to do is not possible (by design) with opaque types.

Instead, you would need to type erase into AnyView:

func getShape(shape:Int, i: Int) -> AnyView {

   switch self.selectedShape {
   case 0: return AnyView(Rectangle()
                          .stroke(Color.pink)
                          .frame (...)
                          )
   case 1: return AnyView(Circle()
                          .stroke(Color.pink)
                          .frame (...)
                          )
   // etc...
}

Upvotes: 1

Related Questions