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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:36:04