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

为什么SwiftUI的@State属性值在sheet(item:)方法内调用时不被保留

问题原因

你遇到的是SwiftUI sheet(item:) 构造方法的闭包求值时机问题:

  • 在iOS 15及更早的系统版本中,sheet(item:) 的内容闭包只会在绑定的item从nil变为非空的那一刻仅求值一次,求值完成后不会随其他@State变量的更新重新渲染。
  • 你在按钮点击事件中给selectedItem和isReseting两个@State变量赋值是在同一个渲染事务中,selectedItem先被赋值触发sheet闭包求值,此时isReseting还未完成更新,所以闭包里拿到的还是初始的nil值。

最优解决方案

不要用两个独立的@State变量控制sheet的内容,把sheet需要的所有参数打包成一个独立的Identifiable类型,确保所有状态在触发sheet时同步传入:

struct Item: Identifiable{
    var id = UUID()
    var name:String
    var active:Bool
}

// 新增sheet配置类型,整合所有sheet需要的参数
struct SheetConfig: Identifiable {
    let id = UUID()
    let item: Item
    let isReseting: Bool
}

struct ContentView: View {
    
    var items:[Item] = [Item(name: "Oranges", active: true),
                    Item(name: "Apples", active: false),
                    Item(name: "Cookies", active: false) ]
    
    // 替换原来的两个独立@State,只用一个控制sheet
    @State private var sheetConfig: SheetConfig?
        
    var body: some View {
        List{
            ForEach(items){ item in
                HStack{
                    Text(item.name)
                    
                    Button(item.active ? "Reset": "Initiate"){
                        // 赋值时直接传入所有需要的参数,保证状态同步
                        sheetConfig = SheetConfig(item: item, isReseting: true)
                        let _ = print("Value after button tap: \(sheetConfig?.isReseting)")
                    }
                    .padding()
                    .background(item.active ? Color.blue: Color.gray)
                    .foregroundColor(.white)
                    .cornerRadius(30)
                    .frame(width: 100, height: 65)
                }
            }
        }
        .sheet(item: $sheetConfig){ config in
            let _ = print("Value in sheet: \(config.isReseting)") // 输出为true
            
            if config.isReseting == true {
                Text("It's reseting!!!")
            }else{
                Text("It's NOT reseting")
            }
        }
    }
}

其他可选方案

  • 如果你只需要兼容iOS 16及以上系统,不需要修改原有代码,系统原生已经支持sheet(item:)闭包随外部@State更新重新渲染。
  • 临时调试可以调换两个@State的赋值顺序,先给isReseting赋值再给selectedItem赋值,部分场景下可以生效,但稳定性不如打包参数的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 21:36:01