0
votes

Using @State in ParentView and @Binding in ChildView we can make a connection between values of 2 variables in a print and child view. Using code like this:

ChildView(valueFromParent: $valueInParent)

Having valueInParent in ParentView using @State and valueFromParent in ChildView using @Binding. That way those 2 variables are related now and changing one will change another.

Is it possible though to have this binding between two views in a ForEach loop using rows' id numbers? Something like this:

ForEach((1...15), id: \.self) {item in
    ChildView(valueFromParent[item]: self.$valueInParent[item])
}

I am aware of another way - creating an array of item to pass to the list with IDs inside an array:

@State private var list = [
        (id: 0, model: ListItemModel()),
        (id: 1, model: ListItemModel()),
        (id: 2, model: ListItemModel()),
        (id: 3, model: ListItemModel()),
        (id: 4, model: ListItemModel())
    ]

Edit: But I wish to avoid the above array with a fixed list of items.

I would like to create a simple prototype using just a ForEach loop like this: ForEach((1...15), id: .self). The problem is I don't know how to access a var's value from a particular row in the list.

1
It is possible, but think twice if it is really what you need, because ForEach(range) is constant container, ie. you won't be able to change its size, ie. adding/removing items in model container either have no effect (on add) or crash (on remove) due to out of range exception. - Asperi
Thanks for telling me about the limitations. Yes, still it’s what I need. It is for prototyping purposes. To create a list very fast and change something inside the rows. It’s not for production - mallow

1 Answers

0
votes

Here is a demo module of possible approach. Hope it will be helpful.

Update: Provided two variants - for array with model and for dictionary with model

1. Variant with array as container for model

import SwiftUI

struct Model {
    var name: String
    var value: Int

    init(_ name: String, _ value: Int) {
        self.name = name
        self.value = value
    }
}

struct DetailsView : View {
    @Binding var item: Model
    var body: some View {
        HStack {
            Text("Name")
            TextField("", text: $item.name)
        }
    }
}

struct Main: View {
    @State var models = [Model("A", 1), Model("B", 2), Model("C", 3), Model("D", 4)]

    var body: some View {
        NavigationView {
            List {
                ForEach(0..<models.count) { i in
                    NavigationLink(destination: DetailsView(item: self.$models[i])) {
                        Text("Model: \(self.models[i].name)")
                    }
                }
            }
        }
    }
}
struct DemoMainDetailByID: View {
    var body: some View {
        Main()
    }
}

struct DemoMainDetailByID_Previews: PreviewProvider {
    static var previews: some View {
        DemoMainDetailByID()
    }
}

2. Variant with dictionary as container for model

struct Main: View {
    @State var models: [Int: Model] = [1: Model("A", 1), 2: Model("B", 2), 3: Model("C", 3), 4: Model("D", 4)]

    var body: some View {
        NavigationView {
            List {
                ForEach(1...4, id: \.self) { i in
                    NavigationLink(destination: DetailsView(item: Binding(self.$models[i])!)) {
                        Text("Model: \(self.models[i]!.name)")
                    }
                }
            }
        }
    }
}