0

I have several shapes names circle1(),circle2(),circle3(), up to circle20() all with slightly different attributes. How can I use forEach in the same way that I could use string interpolation to loop through all of them.

 ForEach(0..<20){ i in
            Image("circle\(i)").offset(x:CGFloat(i * 100),y:0)
}

The above example is for an image and it works fine, but would there be a way to do the same with similar named shapes? Of course the following example below didn't work:

 ForEach(0..<20){ i in
            circle\(i).offset(x:CGFloat(i * 100),y:0)
}
2
  • Nope. If you have variables like this, you should be using an array. Commented Apr 13, 2020 at 7:19
  • 1
    Put all of your circles to an array then foreach that array Commented Apr 13, 2020 at 8:40

2 Answers 2

1

if you really need to use shape names, maybe something like this:

struct MyShape {
var name: String
var shape: AnyView
}

struct ContentView: View {
@State var shapes = [
    MyShape(name: "circle0", shape: AnyView(Circle())),
    MyShape(name: "circle1", shape: AnyView(Rectangle())),
    MyShape(name: "circle2", shape: AnyView(Circle())),
    MyShape(name: "circle3", shape: AnyView(Rectangle())),
    MyShape(name: "circle4", shape: AnyView(Circle()))]

var body: some View {
    Group {
        ForEach(0..<5) { i in
            self.getShapeByName("circle" + String(i)).offset(x: CGFloat(i * 10), y:100)
        }
    }
}

func getShapeByName(_ name: String) -> AnyView {
    if let theShape = shapes.first(where: { $0.name == name }) {
        return theShape.shape
    }
    return AnyView(EmptyView())
}
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! This manages to get majority of the goal done. Only concern is that since it's outputting an AnyView(), it doesn't seem to be possible to use the stroke() and trim() modifiers as Xcode complains about shape protocol, or am I missing something?
I couldn't make an array with shapes of different types, so I used AnyView. If all you have are Circles, then make an array of Circle and then you'll be able to modify them to your liking.
0

you could try something like this, and coupled with using .tag() instead of array index, could get you what you're after.

@State var shapes = [AnyView]()

var body: some View {
    Group {
        ForEach(0..<self.shapes.count, id: \.self) { i in
            self.shapes[i].offset(x: CGFloat(i * 10), y:100)
        }
    }.onAppear(perform: loadShapes)
}

func loadShapes() {
    for i in 0..<10 {
        shapes.append(AnyView(Circle()))
    }
    for i in 0..<10 {
        shapes.append(AnyView(Rectangle()))
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.