Home > Back-end >  SwiftUI - ForEach weird behaviour
SwiftUI - ForEach weird behaviour

Time:10-19

I have a forEach loop inside a view builder function like this:

ForEach(0..<array.count, id: \.id) { index in

array contains a custom model, that conforms to Identifiable and has an id. Problem is when I create another foreach below this one:

ForEach(0..<anotherArray.count, id: \.id) { index in

now, anotherArray also has that custom model type. When running the app it will only show the first foreach, the anotherArray loop is not shown what is inside of it.

I have tried to just discard of the id: .id as this make it work as so:

ForEach(viewModel.array.indices) { index in and
ForEach(viewModel.anotherArray.indices) { index in

It works but the problem is the warning I'm getting: "Non-constant range: not an integer range"

I cannot find a clean solution for this! It's also worth mentioning that I need the loop to return me the index.

Edit: Forgot to mention this is inside a LazyVStack because I need the pinnedViews argument.

Thanks

CodePudding user response:

The rules are

  1. indices, explicit integer ranges or primitive arrays like [String] or [Int] require id: \.self.
  2. An object which does not conform to Identifiable but has an id property requires id: \.id (or another hashable property).
  3. An object which does conform to Identifiable can omit the id parameter.

CodePudding user response:

Found out that one can use .id(UUID()) in the view inside each forEach. It will log this warning in the console:

LazyVStackLayout: the ID 0 is used by multiple child views, this will give undefined results!

But this works! Although I must say I don't know if this will give any strange behaviour, for now I'm not seeing any.

CodePudding user response:

The ForEach View is not a for loop.

You can't use it with array indices because it'll crash if the array changes because indices are not valid identifiers. I.e. if the item at index 1 moves to 0 it still has the index 1. If you want to use integers then it has to be a static range, e.g.

ForEach(0..<5) { i in

}

Otherwise you have to supply the ForEach with an array of structs that have an identifier, or even better implement the Identifiable protocol and an id property.

id:\.self is usually a programmer error because id is supposed to be the keypath to the unique identifier for the data not the data itself.

  • Related