You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:54:58