SwiftUI:Sheet关闭后视图参数未更新的解决方法咨询
问题解决:SwiftUI Sheet切换数据不更新的问题
你的问题出在多个按钮绑定同一个isPresented状态,且Sheet视图使用@State接收参数导致的。SwiftUI会复用Sheet实例,不会重新初始化,所以关闭后点击其他按钮,Sheet还是加载旧的参数。
修复步骤:
- 用
item绑定替代isPresented,跟踪选中的具体数据项 - 移除Sheet视图里的
@State,改用常量接收外部传入的参数
修改后主视图代码:
@State var dic = OrderedDictionary<String, UIImage>() // 用可选元组跟踪选中的图片和URL,初始为nil @State var selectedMedia: (image: UIImage, url: String)? VStack (alignment: .center) { ForEach(dic.keys, id: \.self) { dicObject in Button { // 点击时设置选中项,自动触发Sheet弹出 guard let image = dic[dicObject] else { return } selectedMedia = (image: image, url: dicObject) } label: { Image(uiImage: dic[dicObject]!) .resizable() .frame(width: 300, height: 400) .cornerRadius(20) } // 使用item绑定,选中项变化时会重新创建Sheet实例 .sheet(item: $selectedMedia) { item in GalleryViewSpecific(image: item.image, url: item.url) } } }
修改后Sheet详情视图代码:
// 用let接收外部传入的参数,不需要@State(@State仅用于视图内部状态) let image: UIImage let url: String @Environment(\.dismiss) var dismiss var body: some View { ScrollView { VStack(alignment: .leading) { Button("Press to dismiss") { dismiss() } .font(.title) .padding() .background(.black) Image(uiImage: image) .resizable() .frame(width: 300, height: 400) .cornerRadius(20) Text(url) .foregroundColor(.white) } } .background(Color.black) }
额外优化建议:
- 避免强制解包
dic[dicObject]!,改用if let或guard let防止空值崩溃 - 如果需要更规范的代码结构,可以定义结构体封装数据:
struct MediaItem: Identifiable { let id: String let image: UIImage let url: String }
后续将selectedMedia改为@State var selectedMedia: MediaItem?,ForEach直接遍历dic.map { MediaItem(id: $0.key, image: $0.value, url: $0.key) },代码可读性更强。
内容的提问来源于stack exchange,提问作者Bart
相关产品推荐
相关产品推荐

