【问题标题】:SwiftUI ForEach -- I can't limit number of iterationsSwiftUI ForEach——我不能限制迭代次数
【发布时间】:2020-06-02 22:16:11
【问题描述】:

这是我第一次发帖,但我已经使用这个很棒的资源有一段时间了。我已经查看了这里以及整个互联网上的许多帖子,但还没有找到解决方案(或者我可能错过了它们)。

我是一名新手编码员,正在开发一个使用 SwiftUI 的应用程序,以帮助用户学习几种阿拉斯加本地语言的短语。该应用程序的一部分是“测验”功能,要求用户将口语短语与四张照片中的一张进行匹配。我的 ForEach 循环遇到了问题。我不能传入我的对象数组,它需要一个整数范围......但我不能只说 ForEach(0...3) 因为它因“超出范围”错误而崩溃。我想可能是因为我的参数是一个被计算的@State 变量?

我尝试将其更改为常规 var,但随后出现了一些我必须处理的编译器错误,包括将函数调用更改为 mutating,但后来我无法使用我的 .onAppear(perform:),因为我可以' t 改变结构。

我尝试将 ForEach 部分包装在一个“While”循环中,认为这可能会起作用,但这给了我一个不同的编译器错误。我不确定如何继续。

一些背景知识可能会有所帮助:我的应用程序的“课程”部分每个类别(食物、衣服等)都有许多抽认卡。每张抽认卡以英语以外的两种语言呈现短语、文本和声音。在应用程序的“测验”部分,用户选择了他们想要测验的语言、类别和测验样式。然后,他/她会被引导到适当的视图,并传入适当的参数。这很好用。计算 ForEach 中的参数的原因是,并非抽认卡上的每个短语都适用于每种风格的测验或每种语言。因此,虽然我可能有 15 张抽认卡,但其中只有 12 张在 Yup'ik 中可能有有效的有声照片匹配,但在 Dena'ina 中可能全部 15 张。因此,我的“正确测验卡”参数已被过滤以解决此问题。我怀疑这是我的问题的一部分,但我只是不确定如何完成这项工作,并且在测验中只显示 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()
    }

}


【问题讨论】:

  • 吉姆,对不起,一个愚蠢的问题.. 0..3 是 4 个元素,是的,您要在其中加载 4 个元素?
  • 您好,是的。我希望每个问题都提供四种可供选择的选项。

标签: foreach swiftui swiftui-foreach


【解决方案1】:

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

struct QuizCard: Hashable { ...

然后你可以在ForEach循环中使用correctQuizCards而不使用range

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

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

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

您可以直接使用您的卡:

Image("\(card.imageName)")

【讨论】:

  • 嗨 Pawello,我使 QuizCard 符合 Hashable,并将我的 ForEach 循环更改为您建议的样子,但现在编译器给了我一个错误,提示我需要一个 Int 作为范围。然而,这让我开始思考,我很尴尬,我之前没有想到这一点,我为什么不强制正确的 QuizCards 数组只有四个元素。我在 Stack Overflow 上查找了如何做到这一点并找到了解决方案。使用 Array(someArray.prefix(5) 命令。现在我可以开始了。
  • 作为一个新手,我不确定协议...由于您的解释在技术上不起作用,我不应该将其标记为已解决,对吗?我非常感谢您的帮助,因为它帮助我转动了车轮。
  • 我相信您遇到的错误是因为您尝试在循环中使用number。我更新了我的答案,所以现在更清楚了。我在 Xcode 11.5、Swift 5.1 中测试了我的解决方案。在您的场景中,您真的不需要ForEach 的范围。
  • 这也是 cleaner 代码:将来,如果您决定可以有更多(或更少)正确的问题卡,则不必更改 @987654334 @循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2017-07-05
  • 2020-01-27
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多