如果用户已启用推送通知,请在iPhone上确定

时间:2009-10-08 03:05:09

标签: ios iphone notifications apple-push-notifications push

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

19 个答案:

答案 0 :(得分:300)

致电enabledRemoteNotificationsTypes并检查面具。

例如:

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

iOS 8及以上版本:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]

答案 1 :(得分:99)

quantumpotato的问题:

types

给出
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

可以使用

if (types & UIRemoteNotificationTypeAlert)

而不是

if (types == UIRemoteNotificationTypeNone) 

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

答案 2 :(得分:53)

在最新版本的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;
}

答案 3 :(得分:50)

更新了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
    }

答案 4 :(得分: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");

答案 5 :(得分:25)

Swift 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()
        }
    }
}

答案 6 :(得分:17)

在尝试同时支持iOS8及更低版本时,我使用isRegisteredForRemoteNotifications并没有像凯文所说的那样运气好。相反,我使用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;
}

答案 7 :(得分:15)

不幸的是,这些解决方案都没有提供真正解决问题,因为在提供相关信息时,API严重缺乏。您可以进行一些猜测,但是使用currentUserNotificationSettings(iOS8 +)只是在其当前形式中不足以真正回答问题。虽然这里的很多解决方案似乎都表明,或者isRegisteredForRemoteNotifications更像是一个明确的答案,但事实并非如此。

考虑一下:

带有isRegisteredForRemoteNotifications文档的

说明:

  

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

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

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

警报已开启 徽章已开启 声音开启了 没有。

这绝对没有任何关于其他因素或通知开关本身的指示。

用户实际上可能会关闭徽章,声音和提醒,但仍会在锁定屏幕或通知中心显示。此用户仍应接收推送通知,并且能够在锁定屏幕和通知中心中看到它们。他们有通知开关。但在这种情况下,currentUserNotificationSettings将返回:UIUserNotificationTypeNone。这并不能真正反映用户的实际设置。

可以做出一些猜测:

  • 如果isRegisteredForRemoteNotificationsNO,那么您可以假设此设备从未成功注册过远程通知。
  • 在第一次注册远程通知后,此时回拨到application:didRegisterUserNotificationSettings:包含用户通知设置,因为这是用户第一次注册设置 指示用户根据权限请求选择的内容。如果设置等同于:UIUserNotificationTypeNone以外的任何内容,则授予推送权限,否则拒绝。这样做的原因是,从您开始远程注册过程的那一刻起,用户只能接受或拒绝,接受的初始设置是您在注册过程中设置的设置。

答案 8 :(得分: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;
}

答案 9 :(得分:5)

对于iOS7,之前确实应该使用enabledRemoteNotificationTypes并检查它是否等于(或不等于你想要的)UIRemoteNotificationTypeNone

但是对于iOS8,总是足以只与isRegisteredForRemoteNotifications一起查看上述状态。你还应该检查application.currentUserNotificationSettings.types是否等于(或不等于你想要的东西)UIUserNotificationTypeNone

即使isRegisteredForRemoteNotifications返回currentUserNotificationSettings.types

UIUserNotificationTypeNone也可能返回true。

答案 10 :(得分:4)

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
    // blah blah blah
{
    NSLog(@"Notification Enabled");
}
else
{
    NSLog(@"Notification not enabled");
}

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

答案 11 :(得分:4)

  

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;
    }
}];

答案 12 :(得分: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";

希望它也会帮助别人:) 快乐的编码。

答案 13 :(得分:3)

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

  • 适用于iOS 7及之前 - &gt;使用enabledRemoteNotificationTypes
  • 适用于iOS 8及更高版本 - &gt;使用isRegisteredForRemoteNotifications。

答案 14 :(得分:1)

这个 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")
            }
        }

Ref

答案 15 :(得分: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

答案 16 :(得分: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方法。

答案 17 :(得分:0)

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

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

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

答案 18 :(得分:-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!