Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.enumerated() method not working on array

Tags:

swiftui

I am passing data to a ForEach and had no problems until I used the .enumerated() method. I got the error that:

  1. Generic struct 'ForEach' requires that 'EnumeratedSequence<[String]>' conform to 'RandomAccessCollection'

  2. Type 'EnumeratedSequence<[String]>.Element' (aka '(offset: Int, element: String)') cannot conform to 'Hashable'; only struct/enum/class types can conform to protocols

As for the first error then you'll see in the code that I'm just passing in an array. So I don't understand this error.

As for the second error I'm not sure about this one.

The data being passed into the array is fed from UserDefaults as you'll see in the code below.

import SwiftUI

struct ContentView: View {
    
    @State private var name = ""
    @State private var myArray = [String]()
    @State private var isShowing = false
    @State private var actionSheet = false
    let defaults = UserDefaults.standard
   
    var body: some View {
        VStack {
            Spacer()
            TextField("Insert name", text: $name)
                .padding()
            ScrollView(.horizontal) {
                HStack {
                    ForEach(myArray.enumerated(), id: \.self) { index, name in
                        Circle()
                            .onTapGesture {
                                self.actionSheet.toggle()
                            }
                            .frame(width: 50, height: 50)
                            .actionSheet(isPresented: $actionSheet) {
                                ActionSheet(title: Text("Titles"), message: Text("This is the message"), buttons: [
                                                .default(Text("Delete item")){
                                                    var loaded =  defaults.stringArray(forKey: "myData")
                                                    
                                                }
                                ])
                            }
                    }
                }.padding()
                
            }
            Text(String(myArray.count))
                .font(.system(size: 30, weight: .black, design: .rounded))
                .foregroundColor(.green)
            VStack {
                Button(action: {self.isShowing.toggle() }){ Text("Show")}
                if isShowing {
                    ForEach(myArray, id: \.self) { name in
                    Text(name)
                    }
                }
            }.animation(.interactiveSpring())
            Spacer()
            
            HStack {
                Button(action: {
                   
                    
                }){
                    Text("Delete")
                        .fontWeight(.bold)
                        .padding()
                        .foregroundColor(.white)
                        .background(Color.red)
                        .cornerRadius(10)
                }
                Button(action: {
                    myArray.append(name)
                    defaults.set(myArray, forKey: "myData")
                    self.name = ""
                }){
                    Text("Save")
                        .fontWeight(.bold)
                        .padding()
                        .foregroundColor(.white)
                        .background(Color.blue)
                        .cornerRadius(10)
                }
               

            }
           

        }.onAppear {
            guard let loaded = defaults.object(forKey: "myData") as? [String] else {
                return
            }
            self.myArray = loaded
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Text

like image 650
Sergio Bost Avatar asked Jul 08 '26 23:07

Sergio Bost


2 Answers

ForEach expects a type conforming to RandomAccessCollection, but Array.enumerated() returns an EnumeratedSequence<[Element]>, which only conforms to Sequence.

You can wrap it in an Array to get an array, which conforms to RandomAccessCollection:

ForEach(Array(myArray.enumerated()), id: \.1) { (n, element) in
}

I personally like to use zip

ForEach(zip(myArray.indices, myArray), id: \.1) { (index, element) in
}

because it works with non-integer indices as well.

like image 69
New Dev Avatar answered Jul 13 '26 08:07

New Dev


The enumerated() returns sequence of tuples, which you can convert to array, like

HStack {
    ForEach(Array(myArray.enumerated()), id: \.1) { index, name in
        Circle()
like image 38
Asperi Avatar answered Jul 13 '26 08:07

Asperi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!