Swift iOS检查是否在ios9和ios10中启用了远程推送通知


71

如何检查用户是否在ios 9或ios 10上启用了远程通知?

如果用户不允许或单击“否”,我想切换一条消息,询问他们是否要启用通知。

Answers:


36

此答案已过时,并且在iOS 10上不支持,您可以检查答案。


使用此代码

let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if isRegisteredForRemoteNotifications {
     // User is registered for notification
} else {
     // Show alert user is not registered for notification
}

2
这似乎不适用于iOS10。在模拟器中,我单击了“不允许”,并且此代码仍然表示用户已注册远程通知。
tylerSF'17年

在iOS 10上对我有效。请尝试使用实际设备代替模拟器。
贾斯汀·瓦利

7
它仅告诉您令牌是否曾经生成(设备已注册),而不通知是否被阻止。
KlimczakM '18年

iOS模拟器不支持远程通知。只有本地通知
麦克·卡彭特

2
这不是确定这一点的正确方法。当用户禁用通知时,即使重新启动应用程序,此属性也将继续返回true。这很奇怪,因为它与说明“此方法返回的值考虑了用户接收远程通知的首选项”的文档背道而驰。您还需要检查用户是否也允许通知。
masterwok

143

Apple建议使用UserNotifications框架而不是共享实例。因此,不要忘记导入UserNotifications框架。由于此框架是iOS 10中的新功能,因此只有在为iOS10 +构建的应用中使用此代码才是真正安全的

let current = UNUserNotificationCenter.current()

current.getNotificationSettings(completionHandler: { (settings) in
    if settings.authorizationStatus == .notDetermined {
        // Notification permission has not been asked yet, go for it!
    } else if settings.authorizationStatus == .denied {
        // Notification permission was previously denied, go to settings & privacy to re-enable
    } else if settings.authorizationStatus == .authorized {
        // Notification permission was already granted
    }
})

您可以查看官方文档以获取更多信息:https : //developer.apple.com/documentation/usernotifications


2
在我看来,这是截至2017
Christian Brink

2
为什么不是这if if elseif else
杰里米·巴德

@OgulcanOrhan是的,我知道它可以正常工作-我使用了您的代码并对您的答案进行了投票,以便您知道:)-我只想知道为什么需要调用所有三个条件?我想我是个书呆子
杰里米·巴德

18
是的,我个人会选择使用switch语句。
C. Bess

10
令人惊讶的是,苹果公司的员工们总是如何做到使事情变得如此简单,例如访问两个布尔值成为一堆异步请求。我真的很想知道这样做的原因。
jalone

40

我尝试了Rajat的解决方案,但在iOS 10(Swift 3)上对我不起作用。总是说启用了推送通知。以下是我解决问题的方法。如果用户点击了“不允许”或您尚未询问用户,则显示“未启用”。

let notificationType = UIApplication.shared.currentUserNotificationSettings!.types
    if notificationType == [] {
        print("notifications are NOT enabled")
    } else {
        print("notifications are enabled")
    }

PS:该方法currentUserNotificationSettings在iOS 10.0中已弃用,但仍可以使用。


这可以在iOS 9,8,7等系统上运行吗?还是我需要单独的代码?
康纳·康纳

我不知道,我只检查了在iOS上10
tylerSF

3
卡姆,我刚刚在10.2(在手机上)和9.3(在模拟器上)上测试了此代码,并且在这两者上都可以使用。tylerSF,谢谢您的解决方案。
KeithB

1
该解决方案更好,因为它还可以管理用户输入设置,
启用

6
iOS 10.0中不推荐使用'currentUserNotificationSettings':使用UserNotifications框架的-[UNUserNotificationCenter getNotificationSettingsWithCompletionHandler:]和-[UNUserNotificationCenter getNotificationCategoriesWithCompletionHandler:]
点自由职业者

33

如果您的应用支持iOS 10和iOS 8、9,请使用以下代码

// At the top, import UserNotifications 
// to use UNUserNotificationCenter
import UserNotifications

然后,

if #available(iOS 10.0, *) {
    let current = UNUserNotificationCenter.current()
    current.getNotificationSettings(completionHandler: { settings in

        switch settings.authorizationStatus {

        case .notDetermined:
            // Authorization request has not been made yet
        case .denied:
            // User has denied authorization.
            // You could tell them to change this in Settings
        case .authorized:
            // User has given authorization.
        }
    })
 } else {
     // Fallback on earlier versions
     if UIApplication.shared.isRegisteredForRemoteNotifications {
         print("APNS-YES")
     } else {
         print("APNS-NO")
     }
 }

18

在iOS11中,Swift 4 ...

 UNUserNotificationCenter.current().getNotificationSettings { (settings) in
        if settings.authorizationStatus == .authorized {
            // Already authorized
        }
        else {
            // Either denied or notDetermined
            UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
                (granted, error) in
                  // add your own 
                UNUserNotificationCenter.current().delegate = self
                let alertController = UIAlertController(title: "Notification Alert", message: "please enable notifications", preferredStyle: .alert)
                let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
                    guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
                        return
                    }
                    if UIApplication.shared.canOpenURL(settingsUrl) {
                        UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                        })
                    }
                }
                let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
                alertController.addAction(cancelAction)
                alertController.addAction(settingsAction)
                DispatchQueue.main.async {
                    self.window?.rootViewController?.present(alertController, animated: true, completion: nil)

                }
            }
        }
    }

我对此有误Use of unresolved identifier 'UNUserNotificationCenter'; did you mean 'NSNotificationCenter'?
ChrisO

2
@ChrisO,您必须导入UserNotifications
Faipdeoiad

10

@Rajat的答案还不够。

  • isRegisteredForRemoteNotifications 是您的应用已连接到APNS并获取了设备令牌,这可以用于静默推送通知
  • currentUserNotificationSettings 用于用户权限,没有此权限,则不会将警报,横幅或声音推送通知发送到应用程序

这是支票

static var isPushNotificationEnabled: Bool {
  guard let settings = UIApplication.shared.currentUserNotificationSettings
    else {
      return false
  }

  return UIApplication.shared.isRegisteredForRemoteNotifications
    && !settings.types.isEmpty
}

对于iOS 10,而不是检查currentUserNotificationSettings,您应该使用UserNotifications框架

center.getNotificationSettings(completionHandler: { settings in
  switch settings.authorizationStatus {
  case .authorized, .provisional:
    print("authorized")
  case .denied:
    print("denied")
  case .notDetermined:
    print("not determined, ask user for permission now")
  }
})

推送通知可以通过多种方式传递到我们的应用,我们可以要求

UNUserNotificationCenter.current()
  .requestAuthorization(options: [.alert, .sound, .badge])

用户可以随时转到“设置”应用并关闭其中的任何一个,因此最好在settings对象中进行检查

open class UNNotificationSettings : NSObject, NSCopying, NSSecureCoding {


    open var authorizationStatus: UNAuthorizationStatus { get }


    open var soundSetting: UNNotificationSetting { get }

    open var badgeSetting: UNNotificationSetting { get }

    open var alertSetting: UNNotificationSetting { get }


    open var notificationCenterSetting: UNNotificationSetting { get }
}

2
请注意,从iOS 10开始不推荐使用
Yuchen Zhong

7

这是一种获取字符串的解决方案,该字符串描述了适用于iOS 9(通过iOS 11和Swift 4)的当前权限。此实现使用When for promises。

import UserNotifications

private static func getNotificationPermissionString() -> Promise<String> {
    let promise = Promise<String>()

    if #available(iOS 10.0, *) {
        let notificationCenter = UNUserNotificationCenter.current()
        notificationCenter.getNotificationSettings { (settings) in
            switch settings.authorizationStatus {
            case .notDetermined: promise.resolve("not_determined")
            case .denied: promise.resolve("denied")
            case .authorized: promise.resolve("authorized")
            }
        }
    } else {
        let status = UIApplication.shared.isRegisteredForRemoteNotifications ? "authorized" : "not_determined"
        promise.resolve(status)
    }

    return promise
}

5

即使用户不允许推送通知,设备令牌仍然可用。因此,检查是否允许接收推送通知也是一个好主意。

private func checkPushNotificationAllowed(completionHandler: @escaping (Bool) -> Void) {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getNotificationSettings { (settings) in
            if settings.authorizationStatus == .notDetermined || settings.authorizationStatus == .denied {
                completionHandler(false)
            }
            else {
                completionHandler(true)
            }
        }
    }
    else {
        if let settings = UIApplication.shared.currentUserNotificationSettings {
            if settings.types.isEmpty {
                completionHandler(false)
            }
            else {
                completionHandler(true)
            }
        }
        else {
            completionHandler(false)
        }
    }
}

4
class func isRegisteredForRemoteNotifications() -> Bool {
    if #available(iOS 10.0, *) {
        var isRegistered = false
        let semaphore = DispatchSemaphore(value: 0)
        let current = UNUserNotificationCenter.current()
        current.getNotificationSettings(completionHandler: { settings in
            if settings.authorizationStatus != .authorized {
                isRegistered = false
            } else {
                isRegistered = true
            }
            semaphore.signal()
        })
        _ = semaphore.wait(timeout: .now() + 5)
        return isRegistered
    } else {
        return UIApplication.shared.isRegisteredForRemoteNotifications
    }
}

3
请不要这样做,以使异步操作显示为同步-> _ = semaphore.wait(timeout:.now()+ 5)
Augie

@Augie除了在某些极少数情况下异步操作可能需要5秒钟以上之外,是否有任何特定原因?
ViruMax

2

对于iOS12和Swift 4也支持iOS13和Swift5我也为此创建了一个git,您可以在此处查看

只需在您的XCode项目中添加此单例文件

import Foundation
import UserNotifications


class NotificaionStatusCheck {


    var window: UIWindow?

    private var currentViewController : UIViewController? = nil


     static let shared = NotificaionStatusCheck()

    public func currentViewController(_ vc: UIViewController?) {
        self.currentViewController = vc
        checkNotificationsAuthorizationStatus()
    }


    private func checkNotificationsAuthorizationStatus() {
        let userNotificationCenter = UNUserNotificationCenter.current()
        userNotificationCenter.getNotificationSettings { (notificationSettings) in
            switch notificationSettings.authorizationStatus {
            case .authorized:
                print("The app is authorized to schedule or receive notifications.")

            case .denied:
                print("The app isn't authorized to schedule or receive notifications.")
                self.NotificationPopup()
            case .notDetermined:
                print("The user hasn't yet made a choice about whether the app is allowed to schedule notifications.")
                self.NotificationPopup()
            case .provisional:
                print("The application is provisionally authorized to post noninterruptive user notifications.")
                self.NotificationPopup()
            }
        }

    }

    private func NotificationPopup(){
        let alertController = UIAlertController(title: "Notification Alert", message: "Please Turn on the Notification to get update every time the Show Starts", preferredStyle: .alert)
        let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
            guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
                return
            }
            if UIApplication.shared.canOpenURL(settingsUrl) {
                UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                })
            }
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alertController.addAction(cancelAction)
        alertController.addAction(settingsAction)
        DispatchQueue.main.async {
            self.currentViewController?.present(alertController, animated: true, completion: nil)

        }

    }


}

在ViewController用户上访问此代码,在viewDidLoad上访问

NotificaionStatusCheck.shared.currentViewController(self)

如果notDetermined还没有请求许可,那么将用户发送到设置的意义何在?在这种情况下,应该请求许可。
jzeferino

0

如果您启用了推送通知并且禁用了所有选项(alertSetting,lockScreenSetting等),authorizationStatus则以上所有答案几乎都是正确的,但是authorized您将不会收到任何推送通知。

找出用户是否可以接收远程通知的最合适方法是检查所有这些设置值。您可以使用扩展来实现。

注意:此解决方案适用于iOS 10+。如果您支持旧版本,请阅读以前的答案。

extension UNNotificationSettings {

    func isAuthorized() -> Bool {
        guard authorizationStatus == .authorized else {
            return false
        }

        return alertSetting == .enabled ||
            soundSetting == .enabled ||
            badgeSetting == .enabled ||
            notificationCenterSetting == .enabled ||
            lockScreenSetting == .enabled
    }
}
extension UNUserNotificationCenter {

    func checkPushNotificationStatus(onAuthorized: @escaping () -> Void, onDenied: @escaping () -> Void) {
        getNotificationSettings { settings in
            DispatchQueue.main.async {
                guard settings.isAuthorized() {
                    onDenied()
                    return
                }

                onAuthorized()
            }
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.