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

Kev*_*vin 206 iphone notifications push apple-push-notifications ios

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

Zac*_*ing 300

打电话enabledRemoteNotificationsTypes检查面具.

例如:

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone) 
   // blah blah blah
Run Code Online (Sandbox Code Playgroud)

iOS8及以上版本:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
Run Code Online (Sandbox Code Playgroud)

  • iOS 5:这会检查应用程序使用何种推送通知,无论应用程序在您的手机通知中心内是否有天气.我禁用了我的应用程序的推送通知,但仍然有类型== 6.在禁用声音和警报样式后,我得到了类型== UIRemoteNotificationTypeNone. (19认同)
  • @ZacBowling - "iOS 8"及更高版本的解决方案是错误的,因为它仅检查用户是否注册了远程通知.根据文档:`此方法仅反映在您调用registerForRemoteNotifications方法时开始的远程注册过程的成功完成.此方法不反映由于连接问题,远程通知是否实际可用.此方法返回的值考虑了用户接收远程通知的首选项 (15认同)
  • Apple发生了什么事?我希望我能听到他们对这个问题的回应.如何在不知道这些基本信息的情况下开发出色的应用? (5认同)
  • 所以在我看来你也应该检查`[[UIApplication sharedApplication] currentUserNotificationSettings];` (5认同)
  • 正如quantumpotato所指出的,这个答案不再处理所有情况,也不是一个完整的解决方案. (4认同)

Tim*_*ber 99

我无法评论(声誉不够),但重新:quantumpotato的问题:

在哪里types给出

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
Run Code Online (Sandbox Code Playgroud)

一个人可以使用

if (types & UIRemoteNotificationTypeAlert)
Run Code Online (Sandbox Code Playgroud)

代替

if (types == UIRemoteNotificationTypeNone) 
Run Code Online (Sandbox Code Playgroud)

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

  • 我的回答可能无法直接回答"如何确定应用程序是否在通知中心",但它确实提供了一种检查*用户是否会收到应用程序*通知的方法,我认为这是一个本着精神的答案这个问题.我认为不可能检查前者. (8认同)
  • "if(types&UIRemoteNotificationTypeAlert)"的技巧非常好. (2认同)
  • 在Swift2/XCode7中,按位操作失败,错误_Binary运算符'&'无法应用于两个'UIUserNotificationType'操作数_.您可以使用contains而不是`grantedSettings.types.contains(notificationType)` (2认同)

Kev*_*tre 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 在Swift中我无法执行enabled = types和UIRemoteNotificationTypeAlert.错误:类型不是bool (3认同)
  • 那么本地通知呢?iOS 8现在要求用户允许它们.但是后来如何检查这些是否被允许? (2认同)

ViJ*_*had 53

更新了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()
}
Run Code Online (Sandbox Code Playgroud)

代码为swift3.0,iOS10

    let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
    if isRegisteredForRemoteNotifications {
        // User is registered for notification
    } else {
        // Show alert user is not registered for notification
    }
Run Code Online (Sandbox Code Playgroud)

从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.

}
Run Code Online (Sandbox Code Playgroud)

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

    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
    }
Run Code Online (Sandbox Code Playgroud)


til*_*ilo 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");
Run Code Online (Sandbox Code Playgroud)

  • userNotificationSettings.types和UIUserNotificationTypeNone将始终为false,因为UIUserNotificationTypeNone是空位掩码,缺少其他位.对于你,你只想检查平等. (6认同)

Ada*_*aka 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
    }
Run Code Online (Sandbox Code Playgroud)

适用于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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `getNotificationSettings(...)`是异步的,因此返回内部将被忽略 (4认同)

Sha*_*ssy 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;
}
Run Code Online (Sandbox Code Playgroud)


小智 15

遗憾的是,提供的这些解决方案都没有真正解决问题,因为在提供相关信息时,API在一天结束时严重缺乏.你可以做一些猜测但是使用currentUserNotificationSettings(iOS8 +)只是目前的形式还不足以真正回答这个问题.虽然这里的许多解决方案似乎都暗示了这个或者isRegisteredForRemoteNotifications更确切的答案,但事实并非如此.

考虑一下:

isRegisteredForRemoteNotifications文档状态:

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

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

只要currentUserNotificationSettings它表明四件事之一:

警报已开启徽章已开启声音已开启无.

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

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

可以做出一些猜测:

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


poj*_*omx 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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:这不对.因为这些是有点用的东西,它不能用开关,所以我结束使用这个:

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
UIRemoteNotificationType typesset = (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge);
if((types & typesset) == typesset)
{
    CeldaSwitch.chkSwitch.on = true;
}
else
{
    CeldaSwitch.chkSwitch.on = false;
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*age 5

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

然而,对于iOS8而言,仅仅检查上述状态并不总是足够的isRegisteredForRemoteNotifications.你还应该检查是否application.currentUserNotificationSettings.types等于(或不等于你想要的东西)UIUserNotificationTypeNone!

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


Ofi*_*chi 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;
    }
}];
Run Code Online (Sandbox Code Playgroud)