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

如何在App前台活跃时全局显示异地登录登出提示弹窗?

解决App前台显示异地登录弹窗的方案

核心思路

不用在每个ViewController里重复编写检查逻辑,而是借助AppDelegate的生命周期回调触发登录状态校验,再通过全局工具方法获取当前顶层ViewController来展示弹窗,实现一次编写、全局生效。

具体实现步骤

1. 利用App活跃回调触发状态检查

重写applicationDidBecomeActive方法,每次App从后台回到前台或刚启动进入活跃状态时,自动执行账号登录状态检查:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    // 防止重复发起API请求的标志位
    private var isCheckingLoginStatus = false

    func applicationDidBecomeActive(_ application: UIApplication) {
        checkAccountLoginStatus()
    }

    // 封装登录状态检查逻辑
    private func checkAccountLoginStatus() {
        guard !isCheckingLoginStatus,
              !AuthManager.shared.userLoginSession.isEmpty,
              let tokenlogin = SettingsManager.tokenlogin,
              !tokenlogin.isEmpty,
              let fcmToken = Messaging.messaging().fcmToken else {
            return
        }

        isCheckingLoginStatus = true
        NetworkManager.instance.requestObject(ServiceAPI.start(regID: fcmToken, id: AuthManager.shared.userLoginSession, token: tokenlogin), c: SingleResponse<StartResponse>.self) { [weak self] result in
            guard let self = self else { return }
            self.isCheckingLoginStatus = false
            
            switch result {
            case .success(let response):
                AuthManager.shared.userLoginSession = response.data.apikey ?? ""
            case .failure(let error):
                // 检测到异地登录,显示弹窗并执行登出
                self.show异地登录弹窗(message: error.description)
            }
        }
    }
}

2. 实现全局弹窗与登出逻辑

在AppDelegate中添加获取顶层ViewController的方法,解决无法直接弹窗的问题,同时封装弹窗和登出逻辑:

extension AppDelegate {
    // 获取当前显示的顶层ViewController
    private func 获取顶层ViewController() -> UIViewController? {
        var topVC = UIApplication.shared.keyWindow?.rootViewController
        while let presentedVC = topVC?.presentedViewController {
            topVC = presentedVC
        }
        return topVC
    }

    // 显示异地登录提示弹窗
    private func show异地登录弹窗(message: String) {
        DispatchQueue.main.async { [weak self] in
            guard let self = self, let topVC = self.获取顶层ViewController() else { return }
            
            let alert = UIAlertController(
                title: "账号登录提示",
                message: "您的账号已在其他设备登录,当前设备将被登出。\n错误信息:\(message)",
                preferredStyle: .alert
            )
            
            alert.addAction(UIAlertAction(title: "确定", style: .default) { _ in
                self.执行登出逻辑()
            })
            
            topVC.present(alert, animated: true)
        }
    }

    // 执行登出后的状态清理与页面跳转
    private func 执行登出逻辑() {
        // 清空登录状态
        AuthManager.shared.userLoginSession = ""
        SettingsManager.tokenlogin = nil
        
        // 跳转到登录页面(替换成你的登录ViewController)
        let loginVC = LoginViewController()
        let navVC = UINavigationController(rootViewController: loginVC)
        navVC.modalPresentationStyle = .fullScreen
        
        if let topVC = 获取顶层ViewController() {
            topVC.present(navVC, animated: true)
        }
    }
}

3. 保留FCM Token更新时的检查

在原有的MessagingDelegate扩展中,添加App活跃状态下的检查触发,确保Token更新时也能验证登录状态:

extension AppDelegate: MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        guard let fcmToken = fcmToken else { return }
        print("Firebase registration token: \(fcmToken)")
        
        let dataDict:[String: String] = ["token": fcmToken]
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        
        // 如果当前App处于活跃状态,立即触发一次登录检查
        if UIApplication.shared.applicationState == .active {
            checkAccountLoginStatus()
        }
    }
}

关键注意事项

  • 避免重复请求:加入isCheckingLoginStatus标志位,防止App频繁切换活跃状态时重复发起API请求。
  • 主线程更新UI:弹窗逻辑必须放在主线程执行,所以用DispatchQueue.main.async包裹。
  • 多场景适配:如果项目使用SceneDelegate,需要调整获取顶层ViewController方法,改用UIApplication.shared.connectedScenes来获取当前窗口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 15:55:27