SwiftUI ForEach循环内为每个列表项绑定sheet弹出DetailView的问题
实现方案
核心修改逻辑
- 给
Home视图新增@State private var selectedItem: DataArray?可选状态,用来记录当前需要弹出详情的列表项 - 移除原
ForEach循环内部的sheet修饰符,统一将sheet挂载到List外层,绑定到selectedItem - 列表项
Button的点击事件中,将当前遍历的条目赋值给selectedItem即可触发对应详情页弹出
完整修改后代码
import Foundation import SwiftUI struct DataArray: Identifiable { let id: Int let cities: String let name1: String let name2: String let isBookMark: Bool let isFavorite: Bool } public struct ListDataArray { static let dot = [ DataArray(id: 1, cities: "Baltimore", name1: "John", name2: "Mike", isBookMark: false, isFavorite: false), DataArray(id: 2, cities: "Frederick", name1: "Joe", name2: "Swift", isBookMark: false, isFavorite: false), DataArray(id: 3, cities: "Catonsville", name1: "Susan", name2: "Oliver", isBookMark: false, isFavorite: false), // 后续可继续新增数据 ] } class Prospect: ObservableObject { @Published var datas: [DataArray] = ListDataArray.dot } struct Home: View { @EnvironmentObject var items: Prospect // 新增选中状态 @State private var selectedItem: DataArray? var body: some View { List { ForEach(items.datas) { data in Button { // 点击时赋值当前条目触发弹窗 selectedItem = data } label: { LazyHStack { Text("\(data.id)") .font(.title3) Text(data.cities) .font(.subheadline) } .padding() } } .padding() } // sheet统一挂载在List外层,绑定选中状态 .sheet(item: $selectedItem) { // 此处写弹窗关闭时的逻辑 } content: { model in DetailView(data: model) } } } struct DetailView: View { let data: DataArray var body: some View { VStack(spacing: 10) { Text(data.cities) Text(data.name1) Text(data.name2) } .font(.body) } } struct Home_Previews: PreviewProvider { static var previews: some View { Home() .environmentObject(Prospect()) } }
原写法问题说明
原来将sheet写在ForEach循环内部,会为每一个列表项都单独创建一个sheet实例,既存在性能冗余也容易触发弹窗展示异常。依赖DataArray已经实现的Identifiable协议,用单个可选状态绑定唯一的sheet实例,系统会自动匹配对应数据渲染详情页,是SwiftUI的标准实现方案。
内容的提问来源于stack exchange,提问作者Lian
相关产品推荐
相关产品推荐

