Reputation: 3
I understand that a ForEach loop is typically used to display a view. When I put a ForEach loop inside the action button it pretty much tells me Button action cannot conform to the view protocol. So how can I use a loop to make the button carry out multiple actions?
struct SomeView: View {
var newExercises = [NewExercise]()
var finalExercises = [Exercise]()
var body: some View {
Button(action: {
ForEach(newExercises) { newExercise in
//.getExercise() returns an Exercise object
finalExercises.append(newExercise.getExercise())
}
}) {
Text("Done")
}
}
}
I want the button to add an Exercise (by calling .getExercise()) to the finalExercises array for each newExercise in the newExercises array.
How can I go about doing this?
Upvotes: 0
Views: 2055
Reputation: 151
The new SwiftUI
ForEach
statement returns a View
for each Element
of an Array
. For your code, you simply need to run a Void
, Array<Exercise>.append(newElement: Exercise)
not get multiple View
's, so you can use a for
loop, map
, or Array.forEach(body: (_) throws -> Void)
.
If the order in which the newExercises
are appended matters, the most elegant solution will be mapping each NewExercise
of finalExercises
to a Exercise
, and appending the resulting Array<Exercise>
, with Array<Exercise>.append(contentsOf: Sequence)
.
struct SomeView: View {
@State var newExercises = [NewExercise]()
@State var finalExercises = [Exercise]()
var body: some View {
Button(action: {
self.finalExercises.append(contentsOf:
self.newExercises.map { newExercise -> Exercise in
newExercise.getExercise()
}
)
}) {
Text("Done")
}
}
}
If the order in which the newExercises
are appended does not matter, you can call Array<Exercise>.append(newElement: Exercise)
from newExcercises.forEach
, which is different than a SwiftUI
ForEach
statement:
struct SomeView: View {
@State var newExercises = [NewExercise]()
@State var finalExercises = [Exercise]()
var body: some View {
Button(action: {
self.newExercises.forEach { newExercise in
self.finalExercises.append(newExercise.getExercise())
}
}) {
Text("Done")
}
}
}
The way to complete what you want with a for loop would be simple, but less elegant:
struct SomeView: View {
@State var newExercises = [NewExercise]()
@State var finalExercises = [Exercise]()
var body: some View {
Button(action: {
for newExercise in self.newExercises {
self.finalExercises.append(newExercise.getExercise())
}
}) {
Text("Done")
}
}
}
Upvotes: 1