导航链接跳转倒计时计时器视图触发Thread 1运行时崩溃错误
问题分析与修复方案
崩溃原因排查
你遇到的EXC_BAD_ACCESS错误主要来自两个核心问题:
- 视图结构语法错误:
body中直接返回了VStack和HStack两个独立视图,SwiftUI要求body必须返回单个View,这种写法会导致底层视图渲染时的内存访问异常。 - Timer提前触发风险:
Timer.publish设置了autoconnect(),会在视图初始化时立刻启动,此时如果ViewModel的time属性未完成初始化,调用updateCountdown就可能触发野指针访问。
修复后的完整代码
struct SlideFiveView: View { var time: Int @StateObject private var vm = ViewModel() // 先不自动连接Timer,手动控制启动时机 private let timer = Timer.publish(every: 1, on: .main, in: .common) private let width: Double = 250 // 用变量存储Timer订阅,控制生命周期 @State private var timerCancellable: AnyCancellable? var body: some View { // 用根VStack包裹所有子视图,符合SwiftUI的View要求 VStack(spacing: 30) { SlideOne() Text("\(vm.time)") .font(.system(size: 70, weight: .medium, design: .rounded)) .padding() .frame(width: width) .background(.thinMaterial) .cornerRadius(20) .overlay(RoundedRectangle(cornerRadius: 20) // 补全链式调用的点号 .stroke(Color.gray, lineWidth: 4)) //.alert("Timer done!", isPresented: $vm.showingAlert) HStack(spacing: 50) { Button("Start") { vm.start(minutes: Float(time)) // 点击Start后再启动Timer timerCancellable = timer.autoconnect().sink { _ in vm.updateCountdown() } } Button("Pause") { // 支持暂停,取消Timer订阅 timerCancellable?.cancel() } } } .onDisappear { // 视图消失时取消Timer,避免内存泄漏 timerCancellable?.cancel() } } } // 补充ViewModel的标准实现(确保属性初始化正确) class ViewModel: ObservableObject { @Published var time: Int = 0 @Published var showingAlert = false private var totalSeconds: Int = 0 func start(minutes: Float) { totalSeconds = Int(minutes * 60) time = totalSeconds } func updateCountdown() { guard totalSeconds > 0 else { showingAlert = true return } totalSeconds -= 1 time = totalSeconds } }
关键修复点
- 修复视图结构:用根
VStack包裹所有子视图,确保body返回单个View,解决底层渲染的内存异常。 - Timer手动控制:移除
autoconnect(),改为点击Start后再订阅Timer,避免视图初始化时Timer提前触发访问未初始化的ViewModel属性。 - 语法错误修正:补全
overlay前的点号,确保链式调用正常工作。 - 内存管理优化:用
AnyCancellable管理Timer订阅,视图消失时取消订阅,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Christopher Tengey
相关产品推荐
相关产品推荐

