210

我正在寻找一种方法来确定用户是否通过设置启用或禁用了我的应用程序的推送通知。

4

19 回答 19

301

打电话enabledRemoteNotificationsTypes检查口罩。

例如:

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone) 
   // blah blah blah

iOS8及以上:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
于 2009-10-08T03:13:40.577 回答
101

量子土豆的问题:

由哪里types给出

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

一个可以使用

if (types & UIRemoteNotificationTypeAlert)

代替

if (types == UIRemoteNotificationTypeNone) 

将允许您仅检查是否启用了通知(并且不必担心声音、徽章、通知中心等)。如果“警报样式”设置为“横幅”或“警报”,并且如果“警报样式”设置为“无”,则无论其他设置如何,types & UIRemoteNotificationTypeAlert都会返回第一行代码 ( )。YESNO

于 2012-03-27T22:28:21.827 回答
54

在最新版本的 iOS 中,此方法现已弃用。要同时支持 iOS 7 和 iOS 8,请使用:

UIApplication *application = [UIApplication sharedApplication];

BOOL enabled;

// Try to use the newer isRegisteredForRemoteNotifications otherwise use the enabledRemoteNotificationTypes.
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
    enabled = [application isRegisteredForRemoteNotifications];
}
else
{
    UIRemoteNotificationType types = [application enabledRemoteNotificationTypes];
    enabled = types & UIRemoteNotificationTypeAlert;
}
于 2014-09-19T23:53:52.390 回答
54

更新了 swift4.0 , iOS11 的代码

import UserNotifications

UNUserNotificationCenter.current().getNotificationSettings { (settings) in
   print("Notification settings: \(settings)")
   guard settings.authorizationStatus == .authorized else { return }

   //Not authorised 
   UIApplication.shared.registerForRemoteNotifications()
}

swift3.0 , iOS10 的代码

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

从 iOS9 开始,不推荐使用 swift 2.0 UIRemoteNotificationType,请使用以下代码

let notificationType = UIApplication.shared.currentUserNotificationSettings!.types
if notificationType == UIUserNotificationType.none {
        // Push notifications are disabled in setting by user.
    }else{
  // Push notifications are enabled in setting by user.

}

只需检查是否启用了推送通知

    if notificationType == UIUserNotificationType.badge {
        // the application may badge its icon upon a notification being received
    }
    if notificationType == UIUserNotificationType.sound {
        // the application may play a sound upon a notification being received

    }
    if notificationType == UIUserNotificationType.alert {
        // the application may display an alert upon a notification being received
    }
于 2015-10-01T09:25:36.427 回答
33

您将在下面找到一个涵盖 iOS8 和 iOS7(以及更低版本)的完整示例。请注意,在 iOS8 之前,您无法区分“禁用远程通知”和“仅启用锁屏查看”。

BOOL remoteNotificationsEnabled = false, noneEnabled,alertsEnabled, badgesEnabled, soundsEnabled;

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    // iOS8+
    remoteNotificationsEnabled = [UIApplication sharedApplication].isRegisteredForRemoteNotifications;

    UIUserNotificationSettings *userNotificationSettings = [UIApplication sharedApplication].currentUserNotificationSettings;

    noneEnabled = userNotificationSettings.types == UIUserNotificationTypeNone;
    alertsEnabled = userNotificationSettings.types & UIUserNotificationTypeAlert;
    badgesEnabled = userNotificationSettings.types & UIUserNotificationTypeBadge;
    soundsEnabled = userNotificationSettings.types & UIUserNotificationTypeSound;

} else {
    // iOS7 and below
    UIRemoteNotificationType enabledRemoteNotificationTypes = [UIApplication sharedApplication].enabledRemoteNotificationTypes;

    noneEnabled = enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone;
    alertsEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeAlert;
    badgesEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeBadge;
    soundsEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeSound;
}

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    NSLog(@"Remote notifications enabled: %@", remoteNotificationsEnabled ? @"YES" : @"NO");
}

NSLog(@"Notification type status:");
NSLog(@"  None: %@", noneEnabled ? @"enabled" : @"disabled");
NSLog(@"  Alerts: %@", alertsEnabled ? @"enabled" : @"disabled");
NSLog(@"  Badges: %@", badgesEnabled ? @"enabled" : @"disabled");
NSLog(@"  Sounds: %@", soundsEnabled ? @"enabled" : @"disabled");
于 2015-02-09T14:25:23.473 回答
25

斯威夫特 3+

    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
            // settings.authorizationStatus == .authorized
        })
    } else {
        return UIApplication.shared.currentUserNotificationSettings?.types.contains(UIUserNotificationType.alert) ?? false
    }

适用于 iOS10+ 的 RxSwift Observable 版本:

import UserNotifications
extension UNUserNotificationCenter {
    static var isAuthorized: Observable<Bool> {
        return Observable.create { observer in
            DispatchQueue.main.async {
                current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
                    if settings.authorizationStatus == .authorized {
                        observer.onNext(true)
                        observer.onCompleted()
                    } else {
                        current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in
                            observer.onNext(granted)
                            observer.onCompleted()
                        }
                    }
                })
            }
            return Disposables.create()
        }
    }
}
于 2016-09-23T15:44:58.817 回答
17

在尝试同时支持 iOS8 和更低版本时,我没有isRegisteredForRemoteNotifications像 Kevin 建议的那样使用运气。相反,我使用currentUserNotificationSettings了 ,这在我的测试中效果很好。

+ (BOOL)notificationServicesEnabled {
    BOOL isEnabled = NO;

    if ([[UIApplication sharedApplication] respondsToSelector:@selector(currentUserNotificationSettings)]){
        UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];

        if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
            isEnabled = NO;
        } else {
            isEnabled = YES;
        }
    } else {
        UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
        if (types & UIRemoteNotificationTypeAlert) {
            isEnabled = YES;
        } else{
            isEnabled = NO;
        }
    }

    return isEnabled;
}
于 2015-03-05T11:00:36.203 回答
15

不幸的是,提供的这些解决方案都没有真正解决问题,因为归根结底,在提供相关信息方面严重缺乏 API。您可以做出一些猜测,但是使用currentUserNotificationSettings(iOS8+) 以目前的形式不足以真正回答这个问题。尽管这里的许多解决方案似乎都表明这或者isRegisteredForRemoteNotifications是一个明确的答案,但实际上并非如此。

考虑一下:

isRegisteredForRemoteNotifications文件说明:

如果应用程序当前注册了远程通知,则返回 YES,考虑到任何系统范围的设置...

但是,如果您将一个简单地NSLog放入您的应用程序委托中以观察行为,很明显这不会像我们预期的那样工作。它实际上与已为此应用程序/设备激活的远程通知直接相关。一旦第一次激活,这将始终返回YES。即使在设置(通知)中关闭它们仍然会导致返回YES这是因为,从 iOS8 开始,应用程序可能会注册远程通知,甚至在用户未启用通知的情况下发送到设备,他们可能不会发出警报,徽章和声音,无需用户打开它。静默通知是一个很好的例子,即使通知关闭,您也可以继续执行某些操作。

currentUserNotificationSettings它表示四件事之一而言:

警报开启 徽章开启 声音开启 无开启。

这绝对不会为您提供有关其他因素或通知开关本身的任何指示。

用户实际上可能会关闭徽章、声音和警报,但仍会在锁屏或通知中心显示。该用户应该仍会收到推送通知,并且能够在锁定屏幕和通知中心看到它们。他们打开了通知开关。但是currentUserNotificationSettings会返回:UIUserNotificationTypeNone在这种情况下。这并不能真正表示用户的实际设置。

人们可以做出一些猜测:

  • 如果isRegisteredForRemoteNotifications是,NO那么您可以假设此设备从未成功注册远程通知。
  • 在第一次注册远程通知后,此时application:didRegisterUserNotificationSettings:会进行包含用户通知设置的回调,因为这是用户第一次注册,因此设置指示用户根据权限请求选择的内容。如果设置等于: 之外的任何设置,UIUserNotificationTypeNone则授予推送权限,否则拒绝。原因是从您开始远程注册过程的那一刻起,用户只有接受或拒绝的能力,接受的初始设置是您在注册过程中设置的设置。
于 2016-03-25T14:36:11.353 回答
8

为了完成答案,它可以像这样工作......

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
switch (types) {
   case UIRemoteNotificationTypeAlert:
   case UIRemoteNotificationTypeBadge:
       // For enabled code
       break;
   case UIRemoteNotificationTypeSound:
   case UIRemoteNotificationTypeNone:
   default:
       // For disabled code
       break;
}

编辑:这是不对的。因为这些是按位计算的,所以它不能与开关一起使用,所以我结束了使用它:

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
UIRemoteNotificationType typesset = (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge);
if((types & typesset) == typesset)
{
    CeldaSwitch.chkSwitch.on = true;
}
else
{
    CeldaSwitch.chkSwitch.on = false;
}
于 2013-02-21T17:27:10.230 回答
5

对于 iOS7 及之前的版本,您确实应该使用enabledRemoteNotificationTypes并检查它是否等于(或不等于,取决于您想要的) to UIRemoteNotificationTypeNone

然而对于 iOS8 来说,仅仅检查上面的状态并不总是足够的isRegisteredForRemoteNotifications。您还应该检查是否application.currentUserNotificationSettings.types等于(或不等于,具体取决于您想要的)UIUserNotificationTypeNone

isRegisteredForRemoteNotifications即使currentUserNotificationSettings.types返回也可能返回 true UIUserNotificationTypeNone

于 2015-02-04T14:17:48.280 回答
5

iOS8+(目标 C)

#import <UserNotifications/UserNotifications.h>


[[UNUserNotificationCenter currentNotificationCenter]getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {

    switch (settings.authorizationStatus) {
          case UNAuthorizationStatusNotDetermined:{

            break;
        }
        case UNAuthorizationStatusDenied:{

            break;
        }
        case UNAuthorizationStatusAuthorized:{

            break;
        }
        default:
            break;
    }
}];
于 2017-08-09T13:27:25.477 回答
4
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
    // blah blah blah
{
    NSLog(@"Notification Enabled");
}
else
{
    NSLog(@"Notification not enabled");
}

这里我们从 UIApplication 获取 UIRemoteNotificationType。它表示设置中此应用程序的推送通知状态,您可以轻松检查其类型

于 2014-04-22T15:11:39.737 回答
4

我尝试使用@Shaheen Ghiassy 提供的解决方案支持 iOS 10 及更高版本,但发现了剥夺问题enabledRemoteNotificationTypes。因此,我通过使用isRegisteredForRemoteNotifications而不是enabledRemoteNotificationTypes在 iOS 8 中弃用的解决方案找到了解决方案。下面是我更新的解决方案,对我来说非常有效:

- (BOOL)notificationServicesEnabled {
    BOOL isEnabled = NO;
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(currentUserNotificationSettings)]){
        UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];

        if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
            isEnabled = NO;
        } else {
            isEnabled = YES;
        }
    } else {

        if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]) {
            isEnabled = YES;
        } else{
            isEnabled = NO;
        }
    }
    return isEnabled;
}

我们可以轻松调用这个函数并访问它的Bool值,并可以通过以下方式将其转换为字符串值:

NSString *str = [self notificationServicesEnabled] ? @"YES" : @"NO";

希望它也能帮助其他人:) 快乐的编码。

于 2017-08-21T10:39:15.360 回答
3

尽管 Zac 的答案在 iOS 7 之前是完全正确的,但自从 iOS 8 到来后它已经发生了变化。因为从 iOS 8 开始已弃用enabledRemoteNotificationTypes 。对于 iOS 8 及更高版本,您需要使用isRegisteredForRemoteNotifications

  • 对于 iOS 7 及之前版本 --> 使用 enabledRemoteNotificationTypes
  • 对于 iOS 8 及更高版本 --> 使用 isRegisteredForRemoteNotifications。
于 2014-12-15T15:01:26.697 回答
2

这个Swifty解决方案对我来说效果很好(iOS8+),

方法

func isNotificationEnabled(completion:@escaping (_ enabled:Bool)->()){
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
            let status =  (settings.authorizationStatus == .authorized)
            completion(status)
        })
    } else {
        if let status = UIApplication.shared.currentUserNotificationSettings?.types{
            let status = status.rawValue != UIUserNotificationType(rawValue: 0).rawValue
            completion(status)
        }else{
            completion(false)
        }
    }
}

用法

isNotificationEnabled { (isEnabled) in
            if isEnabled{
                print("Push notification enabled")
            }else{
                print("Push notification not enabled")
            }
        }

参考

于 2017-07-21T10:00:16.650 回答
0

回覆:

这是对的

if (types & UIRemoteNotificationTypeAlert)

但以下也是正确的!(因为 UIRemoteNotificationTypeNone 是 0 )

if (types == UIRemoteNotificationTypeNone) 

见下文

NSLog(@"log:%d",0 & 0); ///false
NSLog(@"log:%d",1 & 1); ///true
NSLog(@"log:%d",1<<1 & 1<<1); ///true
NSLog(@"log:%d",1<<2 & 1<<2); ///true
NSLog(@"log:%d",(0 & 0) && YES); ///false
NSLog(@"log:%d",(1 & 1) && YES); ///true
NSLog(@"log:%d",(1<<1 & 1<<1) && YES); ///true
NSLog(@"log:%d",(1<<2 & 1<<2) && YES); ///true
于 2012-05-16T02:48:57.350 回答
0

在 Xamarin 中,以上所有解决方案都对我不起作用。这是我改用的:

public static bool IsRemoteNotificationsEnabled() {
    return UIApplication.SharedApplication.CurrentUserNotificationSettings.Types != UIUserNotificationType.None;
}

在您更改“设置”中的通知状态后,它也会获得实时更新。

于 2017-08-21T03:34:12.327 回答
0

这是在 Xamarin.ios 中执行此操作的方法。

public class NotificationUtils
{
    public static bool AreNotificationsEnabled ()
    {
        var settings = UIApplication.SharedApplication.CurrentUserNotificationSettings;
        var types = settings.Types;
        return types != UIUserNotificationType.None;
    }
}

如果您支持 iOS 10+,请仅使用 UNUserNotificationCenter 方法。

于 2017-08-01T11:18:26.437 回答
-1

从@ZacBowling 的解决方案构建的完全简单的复制和粘贴代码(https://stackoverflow.com/a/1535427/2298002

这也会将用户带到您的应用设置并允许他们立即启用

我还添加了一个解决方案,用于检查是否启用了位置服务(并带来了设置)

// check if notification service is enabled
+ (void)checkNotificationServicesEnabled
{
    if (![[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
    {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Notification Services Disabled!"
                                                            message:@"Yo don't mess around bro! Enabling your Notifications allows you to receive important updates"
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];

        alertView.tag = 300;

        [alertView show];

        return;
    }
}

// check if location service is enabled (ref: https://stackoverflow.com/a/35982887/2298002)
+ (void)checkLocationServicesEnabled
{
    //Checking authorization status
    if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)
    {

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Location Services Disabled!"
                                                            message:@"You need to enable your GPS location right now!!"
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];

        //TODO if user has not given permission to device
        if (![CLLocationManager locationServicesEnabled])
        {
            alertView.tag = 100;
        }
        //TODO if user has not given permission to particular app
        else
        {
            alertView.tag = 200;
        }

        [alertView show];

        return;
    }
}

// handle bringing user to settings for each
+ (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

    if(buttonIndex == 0)// Cancel button pressed
    {
        //TODO for cancel
    }
    else if(buttonIndex == 1)// Settings button pressed.
    {
        if (alertView.tag == 100)
        {
            //This will open ios devices location settings
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=LOCATION_SERVICES"]];
        }
        else if (alertView.tag == 200)
        {
            //This will open particular app location settings
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
        }
        else if (alertView.tag == 300)
        {
            //This will open particular app location settings
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
        }
    }
}

GLHF!

于 2016-06-22T11:23:58.647 回答