iOS 15 SwiftUI NavigationLink意外自动弹出返回特殊场景求助
问题根因分析
你遇到的自动弹出问题核心是 ForEach 标识项的逻辑问题:
- 你当前使用
ForEach(data.activePersons, id: \.self)来遍历用户列表,Person是值类型结构体,只要内部的orders属性发生修改,整个Person实例的哈希值就会变化 ForEach检测到原有标识的条目消失,会自动销毁对应关联的NavigationLink页面,触发系统自动回退到上一级- 同样的逻辑也出现在订单列表的遍历中,你用索引作为遍历id,订单内容修改后索引对应的内容变化,也会触发同样的问题
修复方案
第一步:给Order结构体添加唯一固定标识
给Order增加Identifiable协议实现,用不变的UUID作为唯一id:
struct Order: Hashable, Identifiable { let id = UUID() var paId: Int var n: Int }
第二步:修改所有ForEach的id为固定唯一属性
- 修改用户列表的遍历id,用用户的id而不是整个实例:
// TabView1中的ForEach修改为 ForEach(data.activePersons, id: \.id) { person in
- 修改订单列表的遍历id,用订单自身的id而不是索引:
// EditPerson中的遍历修改为 ForEach(Array(p.orders.enumerated()), id: \.element.id) { loop, order in Section(header: HStack() { Text("BESTELLUNG " + String(loop+1)) } ) { EPSubview1(data: data, psId: psId, loop: loop) } }
可选加固方案
如果仍有偶发的弹出问题,可以将NavigationLink改为手动绑定模式,将导航状态存储在不会被业务修改的独立变量中:
// 示例:在EPSubview1中增加状态控制导航 @State private var showPastrySelect = false // 替换原有NavigationLink为 Button { data.latestOrder.paId = o1.paId showPastrySelect = true } label: { VStack(alignment: .leading) { Text(String(o1.n) + " x " + data.pastryName(o1.paId)) } } .background( NavigationLink(isActive: $showPastrySelect) { SelectPastry(data: data) .onDisappear() { data.persons[pindex].orders[loop].paId = data.latestOrder.paId } } label: { EmptyView() } )
修改完成后,业务数据修改不会影响ForEach的条目标识,导航栈状态不会被系统误销毁,就不会出现自动回退的问题。
内容的提问来源于stack exchange,提问作者phenolot
相关产品推荐
相关产品推荐

