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

SwiftUI中Sheet触发Implicitly Unwrapped Optional错误及显示异常问题

问题1:Sheet触发时抛出隐式解包可选类型错误

原因

你用!强制解包selectedNumber,尽管点击按钮时先赋值再开启Sheet,但SwiftUI状态更新存在异步性,或是在Sheet生命周期的边缘场景(比如关闭后再次打开),selectedNumber可能处于nil状态,直接强制解包会引发崩溃。另外,isPresented绑定的Sheet和selectedNumber状态无强关联,无法保证Sheet渲染时selectedNumber一定有值。

解决办法

推荐用sheet(item:)替代isPresented,这种方式将Sheet的展示与可选状态变量直接绑定,只有变量非nil时才会弹出Sheet,从根源避免强制解包:

import SwiftUI

struct ContentView: View {
    struct SelectedNumber: Identifiable {
        let id: Int
        let value: Int
    }
    
    @State private var selectedNumber: SelectedNumber?
    
    var body: some View {
        ForEach(0..<10) { i in
            Button("\(i)") {
                selectedNumber = SelectedNumber(id: i, value: i)
            }
        }
        .sheet(item: $selectedNumber) { number in
            Text("\(number.value)")
        }
    }
}

如果坚持用isPresented,可在Sheet内容里做安全解包:

.sheet(isPresented: $isShowingSheet) {
    if let number = selectedNumber {
        Text("\(number)")
    } else {
        Text("未选择数字")
    }
}

问题2:循环内的Sheet始终显示0

原因

循环中每个按钮都绑定同一个isShowingSheet状态,当状态变为true时,SwiftUI会尝试渲染所有绑定该状态的Sheet,但多个Sheet共享同一触发条件时,SwiftUI无法正确识别要展示的目标,最终只会显示循环中第一个创建的Sheet(对应i=0的实例)。

解决办法

同样使用sheet(item:)方式,将选中的数字存入可选状态变量,在循环外绑定一次Sheet即可:

import SwiftUI

extension Int: Identifiable {
    public var id: Int { self }
}

struct ContentView: View {
    @State private var selectedNumber: Int?
    
    var body: some View {
        ForEach(0..<10) { i in
            Button("\(i)") {
                selectedNumber = i
            }
        }
        .sheet(item: $selectedNumber) { number in
            Text("\(number)")
        }
    }
}

内容的提问来源于stack exchange,提问作者The-Wolf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 05:44:53