I am passing data to a ForEach and had no problems until I used the .enumerated() method. I got the error that:
Generic struct 'ForEach' requires that 'EnumeratedSequence<[String]>' conform to 'RandomAccessCollection'
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()
}
}

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.
The enumerated() returns sequence of tuples, which you can convert to array, like
HStack {
ForEach(Array(myArray.enumerated()), id: \.1) { index, name in
Circle()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With