You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI报错:无法将Range<Int>类型转为Binding<C>类型参数

问题描述

我正在用Swift开发一款答题APP,支持多个正确答案,因此使用ForEach循环校验所有答案。但当我尝试切换"correct"变量(使"Correct!"提示仅显示一次)时,出现了报错,错误出现在第77行:ForEach(0 ..< data.answer.count, id: \.self)。请问该如何修复?

import SwiftUI

struct LocationView: View {
    @State private var submit: Bool = false
    @State private var guess = ""
    @State private var correct = false
    var data: Location
    
    var body: some View {
            Text(data.question)
                .padding()
            
            TextField("Answer", text: $guess)
                .padding()
                .overlay(
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.green, lineWidth: 2)
                )
                .padding()
            
            Button(action: {
                submit.toggle()
            }) {
                Text("Submit")
                    .foregroundStyle(.blue)
                    .font(.headline)
            }
            
            if submit {
                ForEach(0 ..< data.answer.count, id: \.self) { answer in
                    if guess == data.answer[answer] {
                        correct.toggle()
                    }
                }

                if correct {
                    Text("Correct!")
                        .foregroundStyle(.green)
                        .font(.headline)
                }
            }
        }
    }
}

#Preview {
    let modelData = ModelData()
    LocationView(data: modelData.locations[0])
}
问题原因

你在ForEach的闭包中直接修改@State变量correct,违反了SwiftUI的视图渲染规则——视图的body是纯计算属性,不能在其中直接修改状态变量,否则会触发异常渲染循环或直接报错。

修复方案

把答案校验逻辑移到按钮的点击事件中,一次性判断用户输入是否匹配任一正确答案,避免在视图渲染流程中修改状态:

import SwiftUI

struct LocationView: View {
    @State private var submit: Bool = false
    @State private var guess = ""
    @State private var correct = false
    var data: Location
    
    var body: some View {
            Text(data.question)
                .padding()
            
            TextField("Answer", text: $guess)
                .padding()
                .overlay(
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.green, lineWidth: 2)
                )
                .padding()
            
            Button(action: {
                // 在按钮点击时完成答案校验
                correct = data.answer.contains(guess)
                submit.toggle()
            }) {
                Text("Submit")
                    .foregroundStyle(.blue)
                    .font(.headline)
            }
            
            if submit {
                if correct {
                    Text("Correct!")
                        .foregroundStyle(.green)
                        .font(.headline)
                } else {
                    // 可选:添加错误提示
                    Text("Wrong answer, try again!")
                        .foregroundStyle(.red)
                        .font(.headline)
                }
            }
        }
    }
}

#Preview {
    let modelData = ModelData()
    LocationView(data: modelData.locations[0])
}
额外说明
  • 用data.answer.contains(guess)替代循环判断,代码更简洁高效,直接完成"输入是否在正确答案数组中"的判断。
  • 将状态修改逻辑放在按钮action闭包中,这是SwiftUI中修改状态的正确时机,不会干扰视图渲染流程。
  • 可添加错误提示,进一步完善用户交互体验。

内容的提问来源于stack exchange,提问作者Unofficial Cuber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:27:35