iOS多页面共享Toolbar上方离线提示视图实现问题
可行解决方案
核心思路是用全局环境对象管理网络状态,将离线提示视图嵌入登录后的主导航上下文内,确保它在Toolbar上方且具备跳转能力,具体实现如下:
1. 完善全局网络状态管理
先把CommonViewViewModel改成可全局共享的环境对象,同时加入网络状态监听逻辑:
import Network class CommonViewViewModel: ObservableObject { @Published var isNetworkActive = true private let monitor = NWPathMonitor() init() { monitor.pathUpdateHandler = { path in DispatchQueue.main.async { self.isNetworkActive = path.status == .satisfied } } let queue = DispatchQueue(label: "NetworkMonitor") monitor.start(queue: queue) } }
2. 在App层级注入环境对象
让整个App都能访问统一的网络状态:
@main struct iOSApp: App { @StateObject private var networkVM = CommonViewViewModel() var body: some Scene { WindowGroup { LoginView() .environmentObject(networkVM) } } }
3. 重构登录后的主导航结构
登录成功后跳转的MainView,要把离线提示放在NavigationStack的上方层级,确保它显示在Toolbar之上,同时处于导航上下文内支持跳转:
struct LoginView: View { @EnvironmentObject private var networkVM: CommonViewViewModel @State private var isLoggedIn = false var body: some View { NavigationStack { // 登录按钮等UI Button("登录") { isLoggedIn = true } .navigationDestination(isPresented: $isLoggedIn) { MainRootView() } } } } // 主页面的根容器,承载离线提示和主导航 struct MainRootView: View { @EnvironmentObject private var networkVM: CommonViewViewModel var body: some View { ZStack(alignment: .top) { // 主导航栈,包含所有登录后的页面 NavigationStack { MainView() .toolbar { // 自定义Toolbar内容 ToolbarItem(placement: .navigationBarTrailing) { Button("设置") {} } } } // 离线提示视图,仅断网时显示,位于Toolbar上方 if !networkVM.isNetworkActive { CommonView() .padding(.top, UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0) } } } } struct MainView: View { var body: some View { Text("主页面内容") .navigationTitle("首页") } }
4. 实现可跳转的CommonView
让CommonView处于导航上下文内,直接用NavigationLink实现跳转:
struct CommonView: View { var body: some View { NavigationLink { // 跳转目标页面,比如网络设置页 Text("网络设置页") .navigationTitle("网络设置") } label: { HStack { Image(systemName: "wifi.slash") Text("当前网络已断开,点击查看设置") .font(.caption) } .padding(.horizontal, 16) .padding(.vertical, 8) .background(Color.orange.opacity(0.8)) .foregroundColor(.white) .frame(maxWidth: .infinity) } } }
方案优势
- 解决方案1的问题:
CommonView现在位于NavigationStack的同级ZStack中,属于导航上下文的一部分,NavigationLink可以正常工作。 - 解决方案2的问题:通过
ZStack(alignment: .top)将CommonView放在最顶层,配合安全区内边距,确保它显示在Toolbar上方,不会被遮挡。 - 全局环境对象保证所有页面的网络状态一致,无需重复监听。
内容的提问来源于stack exchange,提问作者pablo7284
相关产品推荐
相关产品推荐

