0

This is my first time posting but I've been using this wonderful resource for awhile. I've looked at a number of posts on here as well as the internet in general and haven't come across a solution yet (or maybe I've missed them).

I am a novice coder working on an app in SwiftUI to help users learn phrases in a couple of Alaska Native languages. One portion of this app is a "quiz" feature that asks the user match a spoken phrase with one of four photos. I'm running into an issue with my ForEach loop. I can't pass in my array of objects, it wants a range of integers...but I can't just say ForEach(0...3) because it crashes with an 'out of range' error. I think maybe it's because my parameter is an @State variable that gets computed?

I tried changing it to a regular var but then had some compiler errors I had to deal with including changing the function calls to mutating, but then I wasn't able to use my .onAppear(perform:) because I can't mutate the struct.

I tried wrapping the ForEach portion in a "While" loop thinking maybe that would work, but that gave me a different compiler error. I'm not sure how to proceed.

A bit of background that may help: the 'lesson' portion of my app has a number of flashcards per category (food, clothing, etc). Each flashcard presents the phrase, text and sounds in two languages other than English. In the 'quiz' portion of the app the user has selected the language they want to be quizzed on, the category and the quiz style. He/she is then directed to the appropriate view with the appropriate parameters passed in. That's working great. The reason my parameter in the ForEach is computed is the not every phrase on the flashcards works in each style of quiz or with with each language. So although I may have 15 flashcards, only 12 of them might have a valid sound-photo match in Yup'ik but all 15 might in Dena'ina. So my 'correctQuizCards' parameter has been filtered to account for that. I suspect that's part of my problem but I'm just not sure how to make this work and only show 4 photos in the quiz. The code works fine with ForEach(0..

I've shared the code below. Hopefully I did it correct. I removed a couple of functions and variables that are irrelevant for this question (presenting an alert, etc). Thanks in advance for any help!



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()
    }

}


4

1 回答 1

0

如果您可以使您QuizCard符合Hashable您的要求,则不必使用范围。

struct QuizCard: Hashable { ...

然后你可以correctQuizCardsForEach循环中使用而不使用range

ForEach(correctQuizCards, id: \.self) { card in ...

请注意,现在您没有 anumber在循环中。你有一个card. 这意味着,而不是:

Image("\(self.correctQuizCards[number].imageName)")

您可以直接使用您的卡:

Image("\(card.imageName)")
于 2020-06-02T22:28:00.773 回答