iOS 15 RC下动态生成destination的NavigationLink自动pop问题
问题表现
- 仅在iOS 15 RC版本出现,iOS 14版本运行完全正常
- 通过NavigationLink push视图时,若destination为动态生成,新视图会被自动pop
相关代码
NavigationLink( destination: createSettingNavigationLink(name: nameAndImage[0]), label: { CellButton(title: nameAndImage[0], image: nameAndImage[1]) } ) func createSettingNavigationLink(name: String) -> some View { if name == "shop.Settings" { return ShopSettings() } if name == "shop.Goods" { return ShopGoodsManagementPage() } if name == "shop.Order" { return ShopOrderPage() } if name == "Customer Service" { return ServiceListPage(isStore: true) } if name == "shop.Performance" { return PerformanceManagementPage() } if name == "shop.Earnings" { return CommissionSummaryPage() } if name == "shop.Increase_sales" { return BCWebView(urlStr: Constants.increaseSalesGuide) .navigationBarTitle(Text("Increase Sales Guide"), displayMode: .inline) .navigationBarHidden(false) } return EmptyView() }
问题原因
iOS 15 RC版本对SwiftUI的视图身份判定逻辑做了调整,上述代码中createSettingNavigationLink函数不同分支返回的是完全不同类型的视图,没有统一的身份标识。当父视图发生重绘时,SwiftUI会误判当前NavigationLink的destination已经失效,就会自动将已经push的新视图pop掉。
解决方案
方案1:为动态destination添加固定唯一标识
在生成的destination视图后添加.id()修饰符,用和业务绑定的唯一值作为标识,让SwiftUI可以正确识别视图身份,不会因为重绘判定身份变更。
示例修改:
NavigationLink( destination: createSettingNavigationLink(name: nameAndImage[0]) .id(nameAndImage[0]), // 新增id修饰符,用name作为唯一标识 label: { CellButton(title: nameAndImage[0], image: nameAndImage[1]) } )
方案2:统一动态视图的返回类型
将createSettingNavigationLink所有分支的返回视图都用AnyView包装,消除不同视图类型带来的身份判定异常,同时将函数返回值声明为AnyView即可。
示例修改:
func createSettingNavigationLink(name: String) -> AnyView { if name == "shop.Settings" { return AnyView(ShopSettings()) } if name == "shop.Goods" { return AnyView(ShopGoodsManagementPage()) } // 其余分支同理都用AnyView包装 ... return AnyView(EmptyView()) }
方案3:改用手动控制的NavigationLink写法
使用带isActive绑定参数的NavigationLink构造方法,手动控制push状态,避开系统自动判定触发的pop逻辑。
内容的提问来源于stack exchange,提问作者LiangWang
相关产品推荐
相关产品推荐

