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

SwiftUI Stepper组件导航至最后项时触发数组越界致命错误求助

问题分析与解决方案

崩溃根因

你遇到的Fatal error: Index out of range,是因为updateTimer方法里直接用newValue访问steps[newValue]时,newValue超出了数组的有效索引范围。当导航到最后一项时,selected的值可能被设置为等于steps.count(比如你说的6个值,数组索引是0-5,此时selected变成6),直接访问steps[6]自然触发越界崩溃。

修复方案

1. 先做索引合法性校验

在updateTimer开头添加索引范围检查,避免越界访问:

func updateTimer(newValue: Int) {
    timer?.invalidate()
    // 先确保newValue在数组有效索引内
    guard newValue >= 0, newValue < steps.count else {
        return
    }
    guard case .animated(let duration) = steps[newValue] else {
        return
    }
    timer = Timer.scheduledTimer(withTimeInterval: Double(duration),
                                 repeats: false,
                                 block: { _ in
        // 替换成更清晰的判断逻辑
        if selected < steps.count - 1 {
            withAnimation {
                selected += 1
            }
        }
    })
}

2. 从根源限制selected的取值范围

在初始化方法里给selected的绑定值加一层包装,确保它永远不会超出数组索引范围:

public init(selected: Binding<Int>, steps: [Step]) {
    // 初始化时修正越界的selected值
    let clampedValue = min(max(selected.wrappedValue, 0), steps.count - 1)
    // 包装绑定,后续任何修改都会被限制在合法范围内
    self._selected = Binding(
        get: { clampedValue },
        set: { selected.wrappedValue = min(max($0, 0), steps.count - 1) }
    )
    self.steps = steps
}

3. 优化定时器触发判断

原代码里的steps.count > selected + 1等价于selected < steps.count -1,后者语义更直观,建议替换避免逻辑混淆。

调试建议

崩溃时可以在updateTimer开头打印newValue和steps.count的具体数值,确认触发越界时的参数状态,方便进一步排查是否有其他逻辑在修改selected的值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 23:15:49