切换应用后SwiftUI NavigationLink失效,需二次切换才恢复
我正在开发一款iOS平台的充电站应用,为用户提供地图及充电站标记点功能。使用NavigationLink跳转到筛选地图结果的视图,按钮采用自定义样式。但遇到一个异常:切换应用到后台再返回后,该NavigationLink完全无法触发跳转,必须再次切换后台并返回才能恢复正常,且该现象会重复出现。
相关代码(MainView)
import SwiftUI import MapKit import CoreLocationUI import Foundation import AlertToast struct MainView: View { @StateObject var locationController = LocationController() @StateObject var networkController = NetworkController() @State public var showingSheet = false @State public var dismissSheet = false @State private var showToast = false @State public var applyFilters = false @State public var type1 = false @State public var type2 = false @State public var csstype1 = false @State public var csstype2 = false @State public var chademo = false @State public var schuko = false @State public var tesla = false @State public var dc = false @State public var ac1 = false @State public var ac2 = false @State public var ac2s = false @State public var ac3 = false @State public var format: Int = 3 @State public var status: Int = 7 var map: MapView { MapView( locationController: locationController, networkController: networkController, showingSheet: $showingSheet, dismissSheet: $dismissSheet, didSelect: {_ in} ) } var body: some View { NavigationView { ZStack(alignment: .bottom) { map.edgesIgnoringSafeArea(.bottom) LocationButton(.currentLocation) { print("tapped") locationController.requestAllowOnceLocationPermission() } .foregroundColor(.white) .cornerRadius(8) .labelStyle(.iconOnly) .tint(Color("LightBlue")) .padding(.bottom, 100 ) .padding(.leading, 330 ) NavigationLink( destination: FiltersView( applyFilters: $applyFilters, type1: $type1, type2: $type2, csstype1: $csstype1, csstype2: $csstype2, chademo: $chademo, schuko: $schuko, tesla: $tesla, dc: $dc, ac1: $ac1, ac2: $ac2, ac2s: $ac2s, ac3: $ac3, format: $format, status: $status), label: { ZStack { RoundedRectangle(cornerRadius: 8, style: .circular) .fill(Color("LightBlue")) HStack { SwiftUI.Image("Filters") .resizable() .scaledToFit() .padding(10) Text("Φίλτρα") .foregroundColor(.white) .font(.system(size: 15, weight: .regular)) .padding(.trailing, 5) } }.frame(minWidth: 100, maxWidth: 110, minHeight: 40, maxHeight: 40) }) .padding(.bottom, 660 ) .padding(.leading, 250 ) } .background(Color("DeepBlue")) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarLeading) { SwiftUI.Image("Logo") .resizable() .scaledToFit() .frame(width: 100, height: 100) } } .sheet(item: $networkController.activeLocation, onDismiss: onSheetDismiss) { item in BottomSheetView(data: item) .onDisappear() { print("dissapear") } } .onAppear { print("Active View: Main") if applyFilters { networkController.applyFilters = .constant(true) NetworkVariables.FilterOptions.type1 = type1 NetworkVariables.FilterOptions.type2 = type2 NetworkVariables.FilterOptions.csstype1 = csstype1 NetworkVariables.FilterOptions.csstype2 = csstype2 NetworkVariables.FilterOptions.chademo = chademo NetworkVariables.FilterOptions.schuko = schuko NetworkVariables.FilterOptions.tesla = tesla NetworkVariables.FilterOptions.dc = dc NetworkVariables.FilterOptions.ac1 = ac1 NetworkVariables.FilterOptions.ac2 = ac2 NetworkVariables.FilterOptions.ac2s = ac2s NetworkVariables.FilterOptions.ac3 = ac3 NetworkVariables.FilterOptions.format = format NetworkVariables.FilterOptions.status = status Task { await networkController.getToken() showToast.toggle() } applyFilters = false } } } .toast(isPresenting: $showToast){ AlertToast(type: .regular, title: "Βρέθηκαν \(networkController.mapLocations.count) σημεία") } } func onSheetDismiss() { print("sheet dismissed") map.dismissSheet = true } }
解决方案
1. 使用isActive绑定控制导航状态
替换原有的隐式NavigationLink为绑定激活模式,通过状态变量明确控制导航,避免后台切换时的状态丢失:
// 添加状态变量 @State private var isFiltersViewActive = false // 替换原NavigationLink NavigationLink( destination: FiltersView( applyFilters: $applyFilters, type1: $type1, type2: $type2, csstype1: $csstype1, csstype2: $csstype2, chademo: $chademo, schuko: $schuko, tesla: $tesla, dc: $dc, ac1: $ac1, ac2: $ac2, ac2s: $ac2s, ac3: $ac3, format: $format, status: $status ), isActive: $isFiltersViewActive, label: { ZStack { RoundedRectangle(cornerRadius: 8, style: .circular) .fill(Color("LightBlue")) HStack { SwiftUI.Image("Filters") .resizable() .scaledToFit() .padding(10) Text("Φίλτρα") .foregroundColor(.white) .font(.system(size: 15, weight: .regular)) .padding(.trailing, 5) } }.frame(minWidth: 100, maxWidth: 110, minHeight: 40, maxHeight: 40) } ) .padding(.bottom, 660 ) .padding(.leading, 250 )
2. 修复点击区域与层级问题
- 给自定义按钮添加
contentShape确保完整点击区域:
ZStack { /* 原按钮内容 */ } .frame(minWidth: 100, maxWidth: 110, minHeight: 40, maxHeight: 40) .contentShape(Rectangle()) // 确保按钮整体可点击
- 给
NavigationLink添加zIndex,确保它在地图视图上层:
NavigationLink(...) .padding(...) .zIndex(1)
3. 修正onAppear中的状态修改方式
原代码中直接替换Binding的操作会破坏SwiftUI的响应链,改为使用@Published变量:
// 在NetworkController中修改 class NetworkController: ObservableObject { @Published var applyFilters = false // ...其他原有代码 } // 在MainView的onAppear中修改 .onAppear { print("Active View: Main") if applyFilters { networkController.applyFilters = true // 不再使用.constant(true) // ...其他筛选参数赋值代码 Task { await networkController.getToken() showToast.toggle() } applyFilters = false } }
4. 检查地图视图的交互状态
确保地图视图在后台恢复后不会拦截点击事件,可显式设置:
map.edgesIgnoringSafeArea(.bottom) .allowsHitTesting(true)
内容的提问来源于stack exchange,提问作者George Karageorgiou
相关产品推荐
相关产品推荐

