1

I have an array of "Workout Sets" in a struct called WorkoutBuilderView. My issue is that I need to access the contents of that array from a struct that is nested within the WorkoutBuilderView (as seen below). This struct does not need to be nested within the WorkoutBuilderView, but it is preferred. The only thing I really need is to be able to edit the sets array from another struct.

Possibly create an "inout" sort of parameter for a struct? (that only works in methods as far as I'm aware)

  • The array that needs to be accessed is called sets.
  • The location where it needs to be accessed is marked by a comment //access point

The code:

struct WorkoutBuilderView: View {


@State var sets = [WorkoutSet(id: 0, percentage: -1, repetitions: -1, alteredValue: .max)]

var body: some View {
    Background {
        Group {
            ...
            if self.sets.count > 0 {
                ScrollView {
                    ForEach(self.sets) { set in
                        WorkoutSetLayout(index: set.id) //where sets needs to be passed in
                    }
                }

            }
            ...
        }
    }
    }

//this is the struct where the array needs to be accessed
struct BuilderPicker: View {

    let name: String
    let options: Array<String>
    let setIndex: Int


    @State var selectedOption = 0
    var body: some View {
        HStack {
            ...
        }

        .onReceive([self.selectedOption].publisher.first()) { (value) in

            //change sets here
            //access point
            print(value)

        }
    }

}

//layout (sets needs to pass through here too)
struct WorkoutSetLayout: View {
    let index: Int
    var body: some View {
        VStack(alignment: .leading) {
            Text("Set \(index + 1)")
            ...
            //the array needs to go into the BuilderPicker where it will be edited
            BuilderPicker(name: "Weight % of", options: [AlteredValue.max.rawValue, AlteredValue.weight.rawValue], setIndex: index)
            ...
        }
    }
}
//you probably don't need to worry about the Background
struct Background<Content: View>: View {
    private var content: Content

    init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content()
    }

    var body: some View {
        EmptyView()
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
            .overlay(content)
            .padding(.top, 75)
    }
}


}
Eli Front
  • 695
  • 1
  • 8
  • 28

1 Answers1

1

If I correctly understand your question, the @Binding is exactly for this purpose

1) Add binding var to nested struct, as

//layout (sets needs to pass through here too)
struct WorkoutSetLayout: View {
    let index: Int
    @Binding var data: [WorkoutSet]
    ...

2) Bind model in parent with nested via initialiser, as

ForEach(self.sets) { set in
    WorkoutSetLayout(index: set.id, data: self.$sets)
}
Asperi
  • 228,894
  • 20
  • 464
  • 690