it-swarm.com.ru

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

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

201
Kevin

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

Например: 

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

iOS8 и выше:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
300
Zac Bowling

Я не могу комментировать (недостаточно репутации), но проблема re: quantumpotato:

Где types дан

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

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

if (types & UIRemoteNotificationTypeAlert)

вместо 

if (types == UIRemoteNotificationTypeNone) 

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

99
Tim Camber

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

Обновлен код для 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
    }
48
ViJay Avhad

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

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()
        }
    }
}
24
Adam Smaka

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

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

Учти это:

в документации isRegisteredForRemoteNotifications говорится:

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

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

Насколько currentUserNotificationSettings это указывает на одну из четырех вещей:

Оповещения включены Значки включены Звук включен Ни один не включен.

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

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

Несколько предположений можно сделать:

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

Чтобы завершить ответ, это может сработать примерно так ...

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;
}
8
pojomx

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

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

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

5
Peter Verhage

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;
    }
}];
4
Ofir Malachi
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
    // blah blah blah
{
    NSLog(@"Notification Enabled");
}
else
{
    NSLog(@"Notification not enabled");
}

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

4
Hossam Ghareeb

Я пытаюсь поддерживать 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";

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

4
Irfan

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

  • для iOS 7 и ранее -> Использовать enabledRemoteNotificationTypes 
  • для iOS 8 и более поздних версий -> Использовать isRegisteredForRemoteNotifications.
3
Rashmi Ranjan mallick

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

Ссылка

1
Zaid Pathan

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

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

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

0
mr5

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
0
wavespread

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

0
Sune Kjærgård