Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get index in ForEach in SwiftUI

Tags:

swift

swiftui

I have an array and I want to iterate through it initialize views based on array value, and want to perform action based on array item index

When I iterate through objects

ForEach(array, id: \.self) { item in   CustomView(item: item)     .tapAction {       self.doSomething(index) // Can't get index, so this won't work     } } 

So, I've tried another approach

ForEach((0..<array.count)) { index in   CustomView(item: array[index])     .tapAction {       self.doSomething(index)     } } 

But the issue with second approach is, that when I change array, for example, if doSomething does following

self.array = [1,2,3] 

views in ForEach do not change, even if values are changed. I believe, that happens because array.count haven't changed.

Is there a solution for this? Thanks in advance.

like image 824
Pavel Avatar asked Jul 28 '19 20:07

Pavel


2 Answers

This works for me:

Using Range and Count

struct ContentView: View {     @State private var array = [1, 1, 2]      func doSomething(index: Int) {         self.array = [1, 2, 3]     }          var body: some View {         ForEach(0..<array.count) { i in           Text("\(self.array[i])")             .onTapGesture { self.doSomething(index: i) }         }     } } 

Using Array's Indices

The indices property is a range of numbers.

struct ContentView: View {     @State private var array = [1, 1, 2]      func doSomething(index: Int) {         self.array = [1, 2, 3]     }          var body: some View {         ForEach(array.indices) { i in           Text("\(self.array[i])")             .onTapGesture { self.doSomething(index: i) }         }     } } 
like image 91
kontiki Avatar answered Oct 03 '22 01:10

kontiki


Another approach is to use:

enumerated()

ForEach(Array(array.enumerated()), id: \.offset) { index, element in   // ... } 

Source: https://alejandromp.com/blog/swiftui-enumerated/

like image 30
Stone Avatar answered Oct 03 '22 03:10

Stone