SwiftUI ForEach - я не могу ограничить количество итераций
Это мой первый пост, но я уже давно пользуюсь этим замечательным ресурсом. Я просмотрел несколько сообщений здесь, а также в Интернете в целом и еще не нашел решения (или, возможно, я их пропустил).
Я начинающий программист и работаю над приложением на SwiftUI, которое помогает пользователям учить фразы на нескольких языках коренных народов Аляски. Одна часть этого приложения - это функция "викторины", которая просит пользователя сопоставить произнесенную фразу с одной из четырех фотографий. У меня проблема с циклом ForEach. Я не могу передать свой массив объектов, ему нужен диапазон целых чисел... но я не могу просто сказать ForEach(0...3), потому что он вылетает с ошибкой "вне диапазона". Я думаю, может быть, это потому, что мой параметр - это вычисляемая переменная @State?
Я попытался изменить его на обычный var, но потом возникли некоторые ошибки компилятора, с которыми мне пришлось столкнуться, включая изменение вызовов функций на изменение, но тогда я не смог использовать свой.onAppear(выполнить:), потому что я не мог изменить структура.
Я попытался обернуть часть ForEach в цикл "Пока", думая, что это сработает, но это дало мне другую ошибку компилятора. Я не знаю, что делать дальше.
Немного предыстории, которая может помочь: в разделе "Урок" моего приложения есть несколько карточек для каждой категории (еда, одежда и т. Д.). На каждой карточке представлены фразы, текст и звуки на двух языках, кроме английского. В части приложения "викторина" пользователь выбрал язык, на котором он хочет пройти тест, категорию и стиль викторины. Затем он / она направляется в соответствующее представление с переданными соответствующими параметрами. Это отлично работает. Причина, по которой вычисляется мой параметр в ForEach, заключается в том, что не каждая фраза на карточках работает в каждом стиле викторины или с каждым языком. Итак, хотя у меня может быть 15 карточек, только у 12 из них может быть действительное совпадение звука и фотографии в Юп'ике, но у всех 15 может быть в Дена'ине. Итак, мой параметр "correQuizCards" был отфильтрован, чтобы учесть это.Я подозреваю, что это часть моей проблемы, но я просто не знаю, как это сделать, и показываю только 4 фотографии в викторине. Код отлично работает с ForEach(0..
Я поделился кодом ниже. Надеюсь, я все сделал правильно. Я удалил пару функций и переменных, которые не имеют отношения к этому вопросу (отображение предупреждения и т. Д.). Заранее благодарю за любую помощь!
import SwiftUI
struct MatchSoundToPhotoQuizView2: View {
@Environment(\.presentationMode) private var presentationMode
@State private var questionNumber = 1
@State private var correctAnswer = Int.random(in: 0...3)
@State private var correctQuizCards = [QuizCard]()
@State private var allQuizCards = [QuizCard]()
var category: String
var language: String
// to implement later - var quizStyle: String
var body: some View {
VStack{
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}){
Text("Dismiss this quiz")}
Text("This is a \(language) based quiz. Match the sound you hear with one of the pictures.")
.layoutPriority(1)
Button(action: {
switch self.language {
case "Dena'ina":
playSound(sound: "\(self.correctQuizCards[self.correctAnswer].denainaAudio)", type: "mp3")
default:
playSound(sound: "\(self.correctQuizCards[self.correctAnswer].yupikAudio)", type: "mp3")
}
}) {
Image(systemName: "play.circle")
.font(.title)
.padding(8)
.foregroundColor(.white)
.background(Color.blue)
.clipShape(Circle())
}
ForEach(0..<correctQuizCards.count, id: \.self) {number in
Button(action: {
self.photoTapped(number)
})
{
Image("\(self.correctQuizCards[number].imageName)")
.resizable()
.renderingMode(.original)
.scaledToFit()
}
}
}
.onAppear(perform: getCards)
}
func getQuizCards() {
switch language {
case "Dena'ina":
correctQuizCards = allQuizCards.filter{$0.soundMatchesPhotoDenaina == true && $0.category == category}
default:
correctQuizCards = allQuizCards.filter{$0.soundMatchesPhotoYupik == true && $0.category == category}
}
}
func askQuestion() {
correctQuizCards.shuffle()
correctAnswer = Int.random(in: 0...3)
}
func getCards() {
allQuizCards = Bundle.main.decode("\(category)Phrases.json")
getQuizCards()
}
}
1 ответ
Если вы можете сделать свой QuizCard
соответствовать Hashable
вам не нужно использовать диапазоны.
struct QuizCard: Hashable { ...
Тогда вы можете использовать correctQuizCards
в ForEach
цикл без использования range
:
ForEach(correctQuizCards, id: \.self) { card in ...
Обратите внимание, что теперь у вас нет number
в петле. У тебя естьcard
. Это означает, что вместо:
Image("\(self.correctQuizCards[number].imageName)")
Вы можете использовать свою карту напрямую:
Image("\(card.imageName)")