Reputation: 569
Is it possible to add multiple SwiftUI Views to a parent View dynamically & programmatically?
For example suppose we have a basic View such as:
struct MyRectView: View {
var body: some View {
Rectangle()
.fill(Color.red)
.frame(width: 200, height: 200)
}
}
And a Button defined as:
struct MyButtonThatMakesRects: View {
var body: some View {
Button(
action: {
// Create & add Views to parent here?
// ...
},
label: {
Text("tap to create a Rect")
}
)
}
}
Is there any way I can create multiple instances of MyRectView
in a parent View when MyButtonThatMakesRects
is tapped?
My initial thinking was in line with how I would do this in UIKit. That being on button tap, create a new UIView()
, and then use .addSubview(...)
to add it to a parent. Not sure if SwiftUI has similar functionality. Or maybe there is a simpler way to do this that I'm not seeing?
Upvotes: 7
Views: 8244
Reputation: 5803
SwiftUI is functional and reactive, so its output is entirely a reflection of state. You'll have to store and manipulate state that results in a SwiftUI view with your desired outcome. The view is reconstructed from scratch every time its state changes. (Not really, as there's some efficient diffing under the hood, but it's a good mental model to use.)
The simplest way that SwiftUI provides is the @State
property wrapper, so a version of what you're asking for would look something like this:
struct RootView: View {
@State private var numberOfRects = 0
var body: some View {
VStack {
Button(action: {
self.numberOfRects += 1
}) {
Text("Tap to create")
}
ForEach(0 ..< numberOfRects, id: \.self) { _ in
MyRectView()
}
}
}
}
I'm guessing your desired end result is more complicated than that, but you can use @State
or use a property pointing to a separate class that handles your state/model, marked with the @ObservedObject
wrapper, to get to whatever you need.
Upvotes: 13