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

SwiftUI @State属性selectedMaster点击无变化引发程序崩溃问题求助

问题根因

你触发崩溃的核心原因是 sheet(isPresented:) 的内容闭包会在视图渲染阶段提前捕获变量值,而非isPresented变为true时才读取最新状态。点击按钮同时修改两个@State属性时,SwiftUI会批量处理状态更新,存在isPresented已经触发sheet弹出,但selectedMaster还未完成赋值的时序问题,此时强制解包nil就会导致崩溃。
另外你当前通过索引遍历ForEach的写法存在潜在隐患:如果modelData.masters是动态更新的数组(比如Firebase异步拉取数据后变更),索引会发生错位,可能导致你赋值的selectedMaster不是实际点击的条目。

修复方案

1. 替换sheet调用方式

删除不需要的@State var isPresented = false变量,改用SwiftUI专为可选参数场景设计的sheet(item:)接口:该接口只有在绑定的可选值不为nil时才会弹出sheet,且会自动将解包后的非可选值传入内容闭包,完全规避强制解包风险。

2. 优化遍历逻辑

合并重复的列表渲染代码,直接遍历数组元素而非索引,避免动态数组的索引错位问题。

修复后完整代码参考

@EnvironmentObject var modelData: FirebaseModelData
    
@State var selectionString = ""
@State var selectedMaster: Master?

var body: some View {
    ScrollView {
        VStack(spacing: 20.0) {
            LocationSelector()
            Searchbar()
            
            Text("Фильтр по услугам")
                .font(.title3)
            
            ServiceTypeSelection(selectionString: $selectionString)
            
            VStack {
                // 合并过滤逻辑,无需重复写两遍ForEach
                ForEach(modelData.masters.filter { master in
                    selectionString.isEmpty || master.serviceTypes.contains(selectionString)
                }, id: \.self) { master in // 如果Master遵守Identifiable协议,可省略id参数直接写ForEach(filteredMasters)
                    Button {
                        selectedMaster = master
                    } label: {
                        MasterRow(master: master)
                    }
                }
                .buttonStyle(PlainButtonStyle())
            }
        }
    }
    .navigationBarTitle("")
    .navigationBarHidden(true)
    // 使用item版本的sheet,自动管理弹出状态,无需强制解包
    .sheet(item: $selectedMaster) { master in
        MasterView(master: master)
        // iOS15+推荐用系统dismiss环境变量关闭sheet,无需自定义modalMode绑定:在MasterView中声明@Environment(\.dismiss) private var dismiss,需要关闭时调用dismiss()即可
            .environment(\.modalMode, Binding(
                get: { false },
                set: { if !$0 { selectedMaster = nil } }
            ))
    }
}

如果你的Master类型没有遵守Hashable协议,无法使用\.self作为id,可以给Master添加Identifiable协议实现,增加唯一的id属性即可。

内容的提问来源于stack exchange,提问作者user15083246

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 06:39:02