为什么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
相关产品推荐
相关产品推荐

