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

SwiftUI Form中动态切换Picker时出现EXC_BAD_ACCESS崩溃问题

问题原因

这个崩溃是SwiftUI WheelPickerStyle 动态加载场景下的已知底层bug:当你切换到Picker Three时,Picker Two会被从视图树中移除,但SwiftUI内部没有正确释放之前和pickerTwoSelection绑定的内存指针;等你切回Picker Two重新加载滚轮选择器时,框架内部错误访问了已经释放的旧指针,就触发了EXC_BAD_ACCESS崩溃。

这个问题和你当前使用字符串类型作为选择变量的实现完全无关,不需要做字符串转整数再反向映射的修改。

解决方案

只需要给动态显示的Picker Two添加唯一标识,强制SwiftUI每次加载它时都视为全新视图,不复用之前的错误缓存即可,修改点仅一行:在Picker Two的pickerStyle修饰符后添加.id(pickerTwoVisible)。

修改后完整代码
import SwiftUI

struct ContentView: View {
    @State var pickerOneSelection: String = "Picker Two"
    @State var pickerTwoVisible: Bool = false
    @State var pickerTwoSelection: Int = 3
    @State var pickerThreeSelection: String = "Option 1"
    
    var pickerOneOptions = ["Picker Two", "Picker Three"]
    var pickerThreeOptions = ["Option 1", "Option 2", "Option 3"]
    
    var body: some View {
        NavigationView {
            Form {
                Picker("Picker One selection", selection: $pickerOneSelection) {
                    ForEach(pickerOneOptions, id: \.self) {
                        Text($0)
                    }
                } // End of Picker 1
                
                if pickerOneSelection == "Picker Two" {
                    HStack {
                        Text("Picker Two selection")
                        Spacer()
                        Button(String(pickerTwoSelection)) {
                            self.pickerTwoVisible.toggle()
                        }
                    } // End of HStack
                    
                    if pickerTwoVisible {
                        Picker("Picker Two", selection: $pickerTwoSelection) {
                            ForEach(0..<32, id: \.self) {
                                Text(String($0))
                            }
                        }
                        .pickerStyle(WheelPickerStyle())
                        // 仅新增这一行即可解决崩溃
                        .id(pickerTwoVisible)
                    } // End of pickerTwoVisible
                    
                } else {
                    
                    Picker("Picker Three selection", selection: $pickerThreeSelection) {
                        ForEach(pickerThreeOptions, id: \.self) {
                            Text($0)
                        }
                    } // End of Picker 3
                    
                }
            } // End of Form
        } // End of NavigationView
    } // End of body
} // End of ContentView
逻辑说明

id修饰符是SwiftUI用来标识视图唯一性的标记,当id值发生变化时,SwiftUI会直接销毁旧视图实例,重新创建全新的视图实例,不会复用之前的内存缓存,也就避开了框架内部未释放旧指针的bug。你的原有业务逻辑、选择变量的类型都不需要做任何修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 05:06:02