You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS应用非活跃(后台/未运行)时网络断开如何告警用户?

iOS实现云服务告警推送及网络断开告警方案

针对你的需求,我分两大模块来拆解实现细节,都是iOS生态下的标准落地方案:

一、配置云服务推送接收(支持非活跃状态)

iOS的远程推送必须依赖Apple Push Notification Service(APNs),核心是完成APNs集成和云服务的对接:

  • 1. 开启推送权限与证书配置
    先在Apple开发者后台给App开启Push Notification功能,优先使用APNs Auth Key(长期有效,比证书更省心)。然后在App内请求用户的通知授权:

    import UserNotifications
    
    func requestNotificationPermission() {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
            if granted {
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }
    }
    

    把这个方法放在App启动逻辑里调用(比如application(_:didFinishLaunchingWithOptions:)或者SceneDelegate的场景初始化方法)。

  • 2. 注册推送令牌并同步到云服务
    App成功注册APNs后会拿到设备推送令牌,需要把这个令牌传给你的云服务,让它能定向推送告警:

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
        let token = tokenParts.joined()
        // 调用你的云服务接口上传token
        uploadTokenToCloudService(token: token)
    }
    
  • 3. 处理不同状态下的推送

    • App未启动/后台状态:APNs会直接把通知展示在系统通知中心,用户点击后唤醒App。你可以在application(_:didFinishLaunchingWithOptions:)里检测launchOptions是否包含UIApplication.LaunchOptionsKey.remoteNotification来处理告警跳转;也可以通过UNUserNotificationCenterDelegateuserNotificationCenter(_:didReceive:withCompletionHandler:)方法处理通知点击事件。
    • 后台静默处理:如果需要在后台接收推送时做数据更新等逻辑,要在开发者后台开启App的「Remote notifications」后台模式,同时云服务的推送payload里要包含"content-available": 1字段,这样App会在后台被唤醒执行代码。

二、网络断开时的告警提示(覆盖非活跃状态)

要实现网络断开时提示用户可能错过通知,核心是监听网络状态变化,并用本地通知触达用户:

  • 1. 监听网络状态(iOS 12+推荐用NWPathMonitor)
    用系统Network框架替代老旧的Reachability库,监听网络状态变化:

    import Network
    
    class NetworkMonitor {
        static let shared = NetworkMonitor()
        private let monitor = NWPathMonitor()
        private let queue = DispatchQueue(label: "NetworkMonitorQueue")
        private var isNetworkConnected = true
    
        private init() {
            monitor.pathUpdateHandler = { [weak self] path in
                guard let self = self else { return }
                let wasConnected = self.isNetworkConnected
                self.isNetworkConnected = path.status == .satisfied
    
                // 检测到网络从连接变为断开
                if wasConnected && !self.isNetworkConnected {
                    self.sendNetworkDisconnectAlert()
                }
            }
            monitor.start(queue: queue)
        }
    
        private func sendNetworkDisconnectAlert() {
            let appState = UIApplication.shared.applicationState
            if appState == .background || appState == .inactive {
                // 后台/未启动状态用本地通知提示
                let content = UNMutableNotificationContent()
                content.title = "网络断开提醒"
                content.body = "你的网络已断开,可能会错过云服务告警通知"
                content.sound = .default
    
                let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
                UNUserNotificationCenter.current().add(request)
            } else {
                // 前台状态弹Alert提示
                DispatchQueue.main.async {
                    let alert = UIAlertController(title: "网络断开", message: "当前网络已断开,可能会错过云服务告警", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "知道了", style: .default))
                    // 这里需要获取当前最上层的ViewController来present,可自定义扩展实现
                    if let topVC = UIApplication.shared.windows.first?.rootViewController?.topMostViewController() {
                        topVC.present(alert, animated: true)
                    }
                }
            }
        }
    }
    

    注:topMostViewController()是自定义扩展,用来获取当前最上层的ViewController,你可以自己实现这个工具方法。

  • 2. 未启动状态的网络检测
    App未启动时无法监听网络,但可以在启动时检查当前网络状态,如果断开就发送提示:

    // 在App启动方法里调用
    func checkNetworkOnLaunch() {
        let path = NWPathMonitor().currentPath
        if path.status != .satisfied {
            let content = UNMutableNotificationContent()
            content.title = "网络状态提醒"
            content.body = "启动时检测到网络断开,可能已错过部分云服务告警"
            content.sound = .default
            let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
            UNUserNotificationCenter.current().add(request)
        }
    }
    
  • 3. 权限与配置注意

    • 本地通知同样需要用户授权,所以之前的通知权限请求要包含alert等选项。
    • Info.plist中添加NSNetworkUsageDescription字段,说明App访问网络状态的原因(比如"用于检测网络连接状态,避免您错过重要告警通知"),否则会被App Store拒审。

关键注意事项

  • 推送权限申请前最好弹个自定义说明Alert,明确告知用户用途(比如"我们需要推送权限来向您发送云服务的告警通知"),提高用户授权率。
  • 后台静默推送的payload必须符合APNs规范,aps字段里要包含"content-available": 1,如果不需要触发系统通知,就不要加alertsound等字段。
  • NWPathMonitor要注意生命周期,App进入后台后可以继续监听,但如果被系统挂起,监听可能暂停,不过iOS会在网络状态变化时唤醒App(需开启对应后台模式)。

内容的提问来源于stack exchange,提问作者JulianSymes

火山引擎 最新活动