绑定值结合If语句导致App崩溃问题求助
问题分析与解决方案
崩溃原因
当在ViewC中把isLogged设为true时,父视图parentView会立刻销毁ViewA(因为isLogged == false的条件不再满足),但此时ViewC还处于ViewB的NavigationView导航栈中,ViewB又是ViewA的子视图。这种情况下,导航栈内的视图还没来得及被正确弹出就被强制销毁,引发内存引用异常导致崩溃。另外,iOS16上NavigationView已被官方弃用,继续使用也会带来潜在的稳定性问题。
修复方案
方案1:调整状态更新顺序
修改ViewC的按钮逻辑,先关闭导航栈再更新登录状态,确保视图有时间完成弹出动作:
struct ViewC: View { var isLogged: Binding<Bool> var loginNavigationIsActive: Binding<Bool> var body: some View { ZStack { Button("BACK") { // 先关闭导航栈,让ViewC弹出 loginNavigationIsActive.wrappedValue = false // 延迟更新登录状态,确保导航栈操作完成 DispatchQueue.main.async { isLogged.wrappedValue = true } } } } }
方案2:改用iOS16+官方推荐的NavigationStack
替换ViewB中的NavigationView为NavigationStack,新组件的状态管理更稳定:
struct ViewB: View { var isLogged: Binding<Bool> @State private var loginNavigationIsActive = false var body: some View { NavigationStack { ZStack { Button("GO") { loginNavigationIsActive = true } } .navigationDestination(isPresented: $loginNavigationIsActive) { ViewC(isLogged: isLogged, loginNavigationIsActive: $loginNavigationIsActive) } } } }
方案3:给父视图添加过渡动画
通过动画给视图销毁过程留出缓冲时间,避免突然销毁导致的异常:
@main struct parentView: App { @State var isLogged: Bool = false var body: some Scene { WindowGroup { ZStack { Color("F6F6F6").edgesIgnoringSafeArea(.all) if !isLogged { ViewA(isLogged: $isLogged) .transition(.opacity) } } .animation(.easeInOut(duration: 0.2), value: isLogged) } } }
验证建议
优先尝试方案1+方案2的组合,既能解决旧导航组件的兼容性问题,又能避免状态更新时机不当引发的崩溃。测试时点击ViewC的BACK按钮,确认ViewC正常弹出后ViewA再被销毁,即可验证修复效果。
内容的提问来源于stack exchange,提问作者Zajebany Sifl
相关产品推荐
相关产品推荐

