SwiftUI中sheet修饰符内无法读取State变量selectedPlayer怎么解决?
问题根因
selectedPlayer为nil的原因:你使用的sheet(isPresented:content:)API的内容闭包会在视图首次渲染时就捕获变量值,此时selectedPlayer为初始值nil,后续你更新该变量也不会更新闭包内捕获的旧值,所以取值始终为空。- sheet多次调用、多次弹窗的原因:你连续修改两个
@State变量会触发视图body多次重绘,每次重绘都会重新生成sheet实例,触发多次弹出逻辑,就出现了重复弹出的系统报错。
修复方案
完全不需要额外的布尔变量控制显隐,直接使用SwiftUI专门为可选对象弹窗设计的sheet(item:content:)API即可,该API会在绑定的可选对象不为空时自动弹出弹窗,且闭包内会直接传入解包后的非空对象,不存在值捕获滞后的问题。
修复后代码如下:
struct PlayerListingView: View { @State private var selectedPlayer: PlayerEntity? var body: some View { Section { ForEach(players) { player in playerCell(player, onSelect: { p in // 仅需要给选中对象赋值即可触发弹窗 selectedPlayer = p printv("cell selected selectedPlayer: \(selectedPlayer)") }) } } .sheet(item: $selectedPlayer) { player in printv("selectedPlayer: \(player)") // 这里传入的player已经是解包后的非空值 EditPlayerView(player: player) } } }
如果需要在EditPlayerView内部手动关闭弹窗,只需要在该视图内添加环境变量即可,不需要传入绑定的显隐控制变量:
struct EditPlayerView: View { // 引入关闭弹窗的环境方法 @Environment(\.dismiss) private var dismiss let player: PlayerEntity var body: some View { // 你的视图逻辑 Button("关闭") { dismiss() } } }
调用dismiss()方法后系统会自动将selectedPlayer置为nil,同时关闭弹窗。
内容的提问来源于stack exchange,提问作者Shawn
相关产品推荐
相关产品推荐

