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

iOS低版本推送权限是否已询问判断及拒后引导设置问题

解决iOS 10以下版本推送权限的询问状态判断与引导设置问题

嘿,我完全get你的需求——既要在用户拒绝推送权限时引导跳转到设置页,还要准确区分“从未询问过权限”和“已拒绝权限”这两种状态,尤其是iOS 10以下的老版本对吧?这确实是个容易被忽略的细节,因为不同系统版本的推送API差异不小,我来给你梳理一套完整的方案:

核心思路

在iOS 10及以上,UNUserNotificationCenter的API已经能直接给出完整的权限状态(包括是否从未授权、已授权、已拒绝),但iOS 10之前没有这么直观的API,我们需要结合UserDefaults标记和系统代理回调来实现判断。

具体实现步骤

1. 记录权限是否被询问过

在iOS 8-9中,当你调用registerUserNotificationSettings(_:)请求权限后,不管用户选择允许还是拒绝,系统都会触发UIApplicationDelegate的application(_:didRegisterUserNotificationSettings:)方法。我们可以在这个方法里记录“已询问过权限”的标记到UserDefaults中:

func application(_ application: UIApplication, didRegisterUserNotificationSettings settings: UIUserNotificationSettings) {
    // 标记已询问过推送权限
    UserDefaults.standard.set(true, forKey: "hasAskedNotificationPermission")
    UserDefaults.standard.synchronize()
    
    // 如果用户允许,继续注册远程通知
    if settings.types != .none {
        application.registerForRemoteNotifications()
    }
}

对于iOS 7,系统会在调用registerForRemoteNotifications()后弹出权限弹窗,不管用户选择什么,都会触发对应回调,我们可以在这些方法里同样标记:

// iOS 7 注册成功回调
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    UserDefaults.standard.set(true, forKey: "hasAskedNotificationPermission")
    UserDefaults.standard.synchronize()
}

// iOS 7 注册失败(包括用户拒绝)回调
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    UserDefaults.standard.set(true, forKey: "hasAskedNotificationPermission")
    UserDefaults.standard.synchronize()
}

2. 判断权限状态并引导设置

接下来,我们可以写一个统一的工具方法来判断当前的权限状态,以及是否需要引导用户去设置:

func checkNotificationPermissionAndGuide() {
    if #available(iOS 10.0, *) {
        // iOS 10及以上的逻辑,你已经熟悉,这里快速带过
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            DispatchQueue.main.async {
                switch settings.authorizationStatus {
                case .denied:
                    // 用户已拒绝,引导去设置
                    self.showGuideToSettingsAlert()
                case .notDetermined:
                    // 从未询问过,发起权限请求
                    self.requestNotificationPermission()
                default:
                    // 已授权,无需处理
                    break
                }
            }
        }
    } else {
        // iOS 10以下版本的判断逻辑
        let hasAsked = UserDefaults.standard.bool(forKey: "hasAskedNotificationPermission")
        guard let settings = UIApplication.shared.currentUserNotificationSettings() else { return }
        
        if hasAsked {
            if settings.types == .none {
                // 已询问过且用户拒绝,引导去设置
                showGuideToSettingsAlert()
            } else {
                // 已授权,无需处理
            }
        } else {
            // 从未询问过,发起权限请求
            requestNotificationPermission()
        }
    }
}

// 发起推送权限请求的方法(适配iOS 10以下)
func requestNotificationPermission() {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
            // 处理授权结果
        }
    } else {
        let settings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(settings)
    }
}

// 展示引导去设置的弹窗
func showGuideToSettingsAlert() {
    let alert = UIAlertController(title: "推送权限已关闭", message: "请前往设置开启推送权限,以便及时接收通知", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "取消", style: .cancel))
    alert.addAction(UIAlertAction(title: "去设置", style: .default) { _ in
        // 打开APP设置页面
        if let url = URL(string: UIApplicationOpenSettingsURLString) {
            if UIApplication.shared.canOpenURL(url) {
                UIApplication.shared.openURL(url)
            }
        }
    })
    UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true)
}

3. 注意事项

  • 确保在APP启动时(比如application(_:didFinishLaunchingWithOptions:))先初始化推送相关的注册逻辑,避免遗漏状态记录。
  • iOS 10以下的currentUserNotificationSettings()只能获取当前的权限类型,无法直接区分“从未询问”和“已拒绝”,所以必须依赖UserDefaults的标记,这个标记一定要在系统回调中设置,不能自己随便写,否则会出现判断错误。
  • 对于iOS 7,UIApplicationOpenSettingsURLString是从iOS 8开始引入的,所以iOS 7无法直接跳转到APP设置页,这种情况可以提示用户手动去设置里开启(不过iOS 7的用户占比已经极低,可根据你的APP用户群体决定是否适配)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:03:04