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)")
Другие вопросы по тегам