#swiftui
#swiftui
Вопрос:
Я передаю данные в ForEach, и у меня не было проблем, пока я не использовал этот .enumerated()
метод. Я получил сообщение об ошибке, которое:
- Общая структура ‘ForEach’ требует, чтобы ‘EnumeratedSequence<[String]>’ соответствовала ‘RandomAccessCollection’
- Тип ‘EnumeratedSequence<[String]>.Element’ (он же ‘(offset: Int, element: String)’) не может соответствовать ‘Hashable’; только типы struct / enum / class могут соответствовать протоколам
Что касается первой ошибки, то вы увидите в коде, который я просто передаю в массив. Поэтому я не понимаю эту ошибку.
Что касается второй ошибки, я не уверен в этом.
Данные, передаваемые в массив, поступают из UserDefaults, как вы увидите в приведенном ниже коде.
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()
}
}
Ответ №1:
enumerated()
Возвращает последовательность кортежей, которые вы можете преобразовать в массив, например
HStack {
ForEach(Array(myArray.enumerated()), id: .1) { index, name in
Circle()
Ответ №2:
ForEach
ожидает тип , соответствующий RandomAccessCollection
, но Array.enumerated()
возвращает EnumeratedSequence<[Element]>
, который соответствует только Sequence
.
Вы можете обернуть его в Array
, чтобы получить массив, который соответствует RandomAccessCollection
:
ForEach(Array(myArray.enumerated()), id: .1) { (n, element) in
}
Лично мне нравится использовать zip
ForEach(zip(myArray.indices, myArray), id: .1) { (index, element) in
}
потому что он также работает с нецелыми индексами.
Комментарии:
1. Это помогло, мне любопытно, на что ссылается ключевой путь «1» для идентификатора параметра??
2. Он ссылается на второй элемент кортежа, который является элементом массива. Он должен
Hashable
работать