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

SwiftUI:数组无元素时隐藏按钮并解决下标越界问题

解决SwiftUI数组下标越界与动态隐藏按钮问题

你遇到的问题核心是直接通过固定下标访问数组元素,当数组长度不足时必然触发下标越界错误;另外要实现元素不足时隐藏按钮,不能只靠disabled,得用条件渲染来控制按钮是否显示。

一、核心解决思路

  1. 安全访问数组元素:给数组添加安全下标扩展,避免直接硬编码下标导致崩溃;
  2. 动态控制按钮显示:根据当前问题的选项数组长度,用if let判断元素是否存在,存在才渲染对应按钮;
  3. 复用UI代码:把重复的按钮样式抽成独立View,减少冗余代码。

二、修改后的完整代码

import SwiftUI

// 给数组添加安全下标扩展,避免越界崩溃
extension Collection {
    subscript(safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

struct TestModel {
    var text: String?
    var ansver: [String]
    var correctAnswer: String?
}

var test: [TestModel] = [
    TestModel(text: "one", ansver: ["one", "two", "three", "four"], correctAnswer: "one"),
    TestModel(text: "five", ansver: ["five", "six", "seven", "eight"], correctAnswer: "five"),
    TestModel(text: "nine", ansver: ["nine", "ten", "twelve"], correctAnswer: "nine") // 3个元素
]

// 抽离按钮样式,复用代码
struct AnswerButtonLabel: View {
    let text: String
    var body: some View {
        Text(text)
            .foregroundColor(.black)
            .padding()
            .frame(maxWidth: .infinity, alignment: .leading)
            .background(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(Color.blue, lineWidth: 2)
            )
    }
}

struct ContentView: View {
    @State var currentIndex: Int = 0
    @State var score = 0
    
    var body: some View {
        VStack {
            if currentIndex < test.count {
                // 安全访问题目文本,避免强制解包崩溃
                if let questionText = test[currentIndex].text {
                    Text(questionText)
                        .font(.title)
                        .padding(.bottom, 20)
                }
                
                // 第一个按钮:数组有第1个元素才显示
                if let answer1 = test[currentIndex].ansver[safe: 0] {
                    Button(action: {
                        checkAnswer(answer: answer1)
                    }) {
                        AnswerButtonLabel(text: answer1)
                    }
                    .padding(.bottom, 10)
                }
                
                // 第二个按钮:数组有第2个元素才显示
                if let answer2 = test[currentIndex].ansver[safe: 1] {
                    Button(action: {
                        checkAnswer(answer: answer2)
                    }) {
                        AnswerButtonLabel(text: answer2)
                    }
                    .padding(.bottom, 10)
                }
                
                // 第三个按钮:数组有第3个元素才显示
                if let answer3 = test[currentIndex].ansver[safe: 2] {
                    Button(action: {
                        checkAnswer(answer: answer3)
                    }) {
                        AnswerButtonLabel(text: answer3)
                    }
                    .padding(.bottom, 10)
                }
                
                // 第四个按钮:数组有第4个元素才显示
                if let answer4 = test[currentIndex].ansver[safe: 3] {
                    Button(action: {
                        checkAnswer(answer: answer4)
                    }) {
                        AnswerButtonLabel(text: answer4)
                    }
                }
            } else {
                // 所有题目完成后显示得分
                Text("最终得分:\(score)/\(test.count)")
                    .font(.largeTitle)
                    .fontWeight(.bold)
            }
        }
        .padding()
    }
    
    func checkAnswer(answer: String) {
        if test[currentIndex].correctAnswer == answer {
            score += 1
        }
        // 控制索引递增,避免越界
        currentIndex = min(currentIndex + 1, test.count)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

三、关键修改说明

  • 安全下标扩展:通过subscript(safe:)判断下标是否在数组合法范围内,返回可选值,彻底避免下标越界;
  • 条件渲染按钮:每个按钮都通过if let判断对应元素是否存在,不存在则不渲染,实现“元素不足时隐藏按钮”的需求;
  • 修复得分逻辑:原来的buttonAction传空字符串导致无法判断正确答案,现在改为传递实际选项文本;
  • 优化索引控制:用min函数限制索引最大值,防止超出数组范围;
  • 代码复用:把按钮样式抽成AnswerButtonLabel,减少重复代码,方便后续修改样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:12:44