Определите на iPhone, если пользователь включил push-уведомления

Я ищу способ определить, может ли пользователь посредством настроек включать или отключать свои push-уведомления для моего приложения.

Ответ 1

Вызвать enabledRemoteNotificationsTypes и проверить маску.

Например:

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

iOS8 и выше:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]

Ответ 2

вопрос квантового вопроса:

Где types даны

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

можно использовать

if (types & UIRemoteNotificationTypeAlert)

вместо

if (types == UIRemoteNotificationTypeNone) 

позволит вам проверить только, включены ли уведомления (и не беспокоиться о звуках, значках, центре уведомлений и т.д.). Первая строка кода (types & UIRemoteNotificationTypeAlert) вернет YES если для "Alert Style" установлено значение "Banners" или "Alerts", и NO если для "Alert Style" установлено значение "None", независимо от других настроек.

Ответ 3

В последней версии 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;
}

Ответ 4

Обновленный код для 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.

}

просто проверьте, включены ли Push-уведомления

    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
    }

Ответ 5

Ниже вы найдете полный пример, который охватывает как 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");

Ответ 6

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
    }

Наблюдаемая версия RxSwift для iOS10 +:

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

Ответ 7

В попытке поддержать 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;
}

Ответ 8

К сожалению, ни одно из этих решений не решило проблему, потому что в конце концов API-интерфейсы серьезно не хватает, когда дело доходит до предоставления соответствующей информации. Вы можете сделать несколько догадок, однако использование currentUserNotificationSettings (iOS8 +) просто недостаточно в его текущей форме, чтобы действительно ответить на вопрос. Хотя многие решения здесь, похоже, предполагают, что либо это, либо isRegisteredForRemoteNotifications является скорее окончательным ответом, на самом деле это не так.

Рассмотрим это:

с isRegisteredForRemoteNotifications документацией указано:

Возвращает YES, если приложение в настоящее время зарегистрировано для удаленных уведомлений, принимая во внимание любые системные настройки...

Однако, если вы просто пропустите NSLog в свой делегат приложения, чтобы наблюдать за поведением, это ясно, что это не ведет себя так, как мы ожидаем, что он будет работать. Фактически это относится непосредственно к удаленным уведомлениям, которые были активированы для этого приложения/устройства. После активации в первый раз это всегда будет возвращать YES. Даже отключение их в настройках (уведомления) по-прежнему приведет к возврату YES, это связано с тем, что с iOS8 приложение может регистрироваться для удаленных уведомлений и даже отправлять на устройство без того, чтобы пользователь не включал уведомления, они просто не могут делать оповещения, значки и звук без включения пользователя. Тихие уведомления - хороший пример того, что вы можете продолжать делать даже при отключенных уведомлениях.

Что касается currentUserNotificationSettings, это указывает на одну из четырех вещей:

Предупреждения включены Значки включены Звук включен Нет.

Это дает вам абсолютно никаких указаний относительно других факторов или самого переключателя уведомления.

Пользователь может фактически отключить значки, звук и оповещения, но все же показывать их на заблокированном экране или в центре уведомлений. Этот пользователь все равно должен получать push-уведомления и иметь возможность видеть их как на экране блокировки, так и в центре уведомлений. Они активируют уведомление. НО currentUserNotificationSettings вернет: UIUserNotificationTypeNone в этом случае. Это действительно не указывает на фактические настройки пользователей.

Несколько догадок можно сделать:

  • if isRegisteredForRemoteNotifications is NO, то вы можете предположить, что это устройство никогда не было успешно зарегистрировано для удаленных уведомлений.
  • после первого времени регистрации для удаленных уведомлений в этот момент выполняется обратный вызов application:didRegisterUserNotificationSettings:, содержащий настройки пользовательских уведомлений, так как это первый раз, когда пользователь был зарегистрирован, настройки должны указывать, что пользователь выбрал с точки зрения запрос разрешения. Если настройки приравниваются к чему-либо другому, кроме: UIUserNotificationTypeNone, то разрешение на принудительное предоставление было предоставлено, в противном случае оно было отклонено. Причина этого заключается в том, что с момента запуска процесса удаленной регистрации у пользователя есть возможность принимать или отклонять, причем начальные настройки приема - это настройки, которые вы настраиваете во время процесса регистрации.

Ответ 9

Чтобы выполнить ответ, он может работать примерно так:

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

edit: Это неправильно. так как это бит-мудрый материал, он не будет работать с коммутатором, поэтому я закончил использовать это:

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

Ответ 10

Для iOS7 и прежде чем вы действительно будете использовать enabledRemoteNotificationTypes и проверьте, равно ли оно (или не соответствует в зависимости от того, что вы хотите) до UIRemoteNotificationTypeNone.

Однако для iOS8 это не всегда достаточно, чтобы проверять только с isRegisteredForRemoteNotifications, как и на указанное выше состояние. Вы также должны проверить, равен ли application.currentUserNotificationSettings.types (или не соответствует в зависимости от того, что вы хотите) UIUserNotificationTypeNone!

isRegisteredForRemoteNotifications может возвращать значение true, даже если currentUserNotificationSettings.types возвращает UIUserNotificationTypeNone.

Ответ 11

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

Здесь мы получаем UIRemoteNotificationType из UIApplication. Он представляет состояние push-уведомления этого приложения в настройке, чем вы можете легко проверить его тип

Ответ 12

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

Ответ 13

Я пытаюсь поддерживать iOS 10 и выше, используя решение, предоставляемое @Shaheen Ghiassy, но обнаруживаю, что проблема с лишением 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";

Надеюсь, это тоже поможет другим :) Счастливое кодирование.

Ответ 14

Хотя ответ Zac был совершенно корректным до iOS 7, он изменился с момента выхода iOS 8. Поскольку enabledRemoteNotificationTypes устарел от iOS 8 и далее. Для iOS 8 и более поздних версий вам необходимо использовать isRegisteredForRemoteNotifications.

  • для iOS 7 и раньше → Использовать enabledRemoteNotificationTypes
  • для iOS 8 и более поздних → Использовать isRegisteredForRemoteNotifications.

Ответ 15

Это решение 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")
            }
        }

Ссылка

Ответ 16

Re:

это правильно

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

Ответ 17

Вот как это сделать в 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.

Ответ 18

В Xamarin все вышеописанное решение не работает для меня. Это то, что я использую вместо этого:

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

Он получает обновление в реальном времени также после того, как вы изменили статус уведомления в настройках.

Ответ 19

Полный код для копирования и вставки, созданный из решения @ZacBowling (fooobar.com/info/33897/...)

это также приведет пользователя к настройкам вашего приложения и позволит им немедленно включить

Я также добавил в решение для проверки включенности служб определения местоположения (и также приводит к настройкам)

// 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!