netshark1000
netshark1000

Reputation: 7413

SwiftUI: Nest views recursively

I try to create a View which is a circle and within the circle there should be added more circles until my recursive function ends. E.g. if I call createSubCircle(depth: 4) I expect 4 circles within itself, where each sub circle should have 80% of it's parent. All circles must have the same center.

The code below returns

Function opaque return type was inferred as 'ZStack<_ConditionalContent<GeometryReader<TupleView<(some View, some View)>>, EmptyView>>', which defines the opaque type in terms of itself

struct ContentView: View {
var body: some View {
    createSubCircle(depth: 4)
}

@ViewBuilder
func createSubCircle(depth: Int) -> some View {
    
    ZStack {
        if depth > 0 {
            GeometryReader{proxy in
                Circle()
                    .strokeBorder(.green, lineWidth: 4)
                    .frame(width: proxy.size.width*0.8, height: proxy.size.height*0.8, alignment: .center)
                createSubCircle(depth: depth-1)
            }
        }
        else{
            EmptyView()
        }
    }
}

}

Upvotes: 2

Views: 505

Answers (2)

0xWood
0xWood

Reputation: 1534

Only way around this I found is type erasure 😢 e.g.

@ViewBuilder
  func createSubCircle(depth: Int) -> some View {
    AnyView(
      ZStack {
        if depth > 0 {
          createSubCircle(depth: depth - 1)
        }
      }
    )
  }

ps you don't need the else EmptyView in a ViewBuilder - it's implied.

Upvotes: 1

Simone Pistecchia
Simone Pistecchia

Reputation: 2840

why don't use ForEach?

@ViewBuilder
func createSubCircle(depth: Int) -> some View {
    ZStack {
        ForEach(0..<depth, id:\.self) {dep in
            GeometryReader{proxy in
                let width = proxy.size.width * (pow(0.8, CGFloat(dep)))
                let height = proxy.size.height * (pow(0.8, CGFloat(dep)))
                ZStack {
                    Circle()
                        .strokeBorder(.green, lineWidth: 4)
                        .frame(width: width, height: height, alignment: .center)
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                }

            }
        }
    }
}

Upvotes: -2

Related Questions