Ответы:
Позвони enabledRemoteNotificationsTypes
и проверь маску.
Например:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
// blah blah blah
iOS8 и выше:
[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
iOS 8
и выше является неправильным, потому что оно проверяет, только если пользователь зарегистрирован для удаленного уведомления. Согласно документации:This method reflects only the successful completion of the remote registration process that begins when you call the registerForRemoteNotifications method. This method does not reflect whether remote notifications are actually available due to connectivity issues. The value returned by this method takes into account the user’s preferences for receiving remote notifications.
[[UIApplication sharedApplication] currentUserNotificationSettings];
проблема кванумпумато:
Где types
дано
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
можно использовать
if (types & UIRemoteNotificationTypeAlert)
вместо того
if (types == UIRemoteNotificationTypeNone)
позволит вам проверять только, включены ли уведомления (и не беспокоиться о звуках, значках, центре уведомлений и т. д.). Первая строка кода ( types & UIRemoteNotificationTypeAlert
) вернется, YES
если для «Alert Style» установлено значение «Banners» или «Alerts», а для NO
«Alert Style» установлено значение «None», независимо от других настроек.
grantedSettings.types.contains(notificationType)
В последней версии 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;
}
UserNotifications
. У меня нет полного ответа сейчас, к сожалению.
Обновлен код для 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
}
Ниже вы найдете полный пример, который охватывает как 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");
Свифт 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()
}
}
}
getNotificationSettings(...)
является асинхронным, поэтому возвращение внутрь будет игнорироваться
Пытаясь поддерживать 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;
}
isEnabled = NO;
в ваших if
случаях он не нужен, так как он был инициализирован какNO
К сожалению, ни одно из этих решений не решило проблему, потому что в конце концов API не хватает, когда дело доходит до предоставления соответствующей информации. Вы можете сделать несколько предположений, однако использование currentUserNotificationSettings
(iOS8 +) просто не достаточно в его текущей форме, чтобы действительно ответить на вопрос. Хотя многие решения здесь, кажется, предполагают, что либо это, либо isRegisteredForRemoteNotifications
скорее окончательный ответ, на самом деле это не так.
Учти это:
с isRegisteredForRemoteNotifications
документацией гласит:
Возвращает YES, если приложение в настоящее время зарегистрировано для удаленных уведомлений, принимая во внимание любые системные настройки ...
Однако, если вы просто NSLog
добавляете делегата в свое приложение для наблюдения за поведением, становится ясно, что это не так, как мы ожидаем, это будет работать. Это на самом деле относится непосредственно к удаленным уведомлениям, активированным для этого приложения / устройства. После первого включения это всегда будет возвращаться YES
. Даже отключение их в настройках (уведомлениях) все равно приведет к этому возвращению, YES
потому что, начиная с iOS8, приложение может регистрироваться для удаленных уведомлений и даже отправлять на устройство, если у пользователя не включены уведомления, они просто могут не делать оповещения, Значки и звук без включения пользователя. Тихие уведомления являются хорошим примером того, что вы можете продолжать делать даже с отключенными уведомлениями.
Насколько currentUserNotificationSettings
это указывает на одну из четырех вещей:
Предупреждения включены Значки включены Звук включен Ни один не включен.
Это не дает вам абсолютно никаких указаний относительно других факторов или самого переключателя уведомлений.
Пользователь может на самом деле отключить значки, звук и оповещения, но все равно будет отображаться на экране блокировки или в центре уведомлений. Этот пользователь все еще должен получать push-уведомления и иметь возможность видеть их как на экране блокировки, так и в центре уведомлений. У них включено уведомление. НО currentUserNotificationSettings
вернется: UIUserNotificationTypeNone
в таком случае. Это не совсем указывает на фактические настройки пользователей.
Несколько предположений можно сделать:
isRegisteredForRemoteNotifications
это так, NO
вы можете предположить, что это устройство никогда не было успешно зарегистрировано для удаленных уведомлений.application:didRegisterUserNotificationSettings:
содержащий настройки уведомлений пользователя, поскольку это первый раз, когда пользователь был зарегистрирован, в настройках должно указываться то, что пользователь выбрал с точки зрения запроса на разрешение. Если настройки равны чему-либо кроме: UIUserNotificationTypeNone
тогда разрешение на передачу было предоставлено, в противном случае оно было отклонено. Причина этого заключается в том, что с момента начала процесса удаленной регистрации пользователь имеет возможность только принять или отклонить, при этом начальные настройки принятия - это настройки, которые вы установили в процессе регистрации.Чтобы завершить ответ, это может сработать примерно так ...
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;
}
Для iOS7 и прежде вы должны действительно использовать enabledRemoteNotificationTypes
и проверить, равно ли оно (или не равно в зависимости от того, что вы хотите) UIRemoteNotificationTypeNone
.
Однако для iOS8 не всегда достаточно проверять только isRegisteredForRemoteNotifications
столько состояний, сколько указано выше. Вы также должны проверить, application.currentUserNotificationSettings.types
равно ли (или не равно в зависимости от того, что вы хотите) UIUserNotificationTypeNone
!
isRegisteredForRemoteNotifications
может вернуть true, даже если currentUserNotificationSettings.types
возвращается UIUserNotificationTypeNone
.
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;
}
}];
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
// blah blah blah
{
NSLog(@"Notification Enabled");
}
else
{
NSLog(@"Notification not enabled");
}
Здесь мы получаем UIRemoteNotificationType из UIApplication. Он представляет состояние push-уведомлений этого приложения в настройках, чем вы можете легко проверить его тип
Я пытаюсь поддерживать 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";
Надеюсь, это поможет и другим :) Счастливого кодирования.
Хотя ответ Zac был совершенно верным до iOS 7, он изменился с тех пор, как появилась iOS 8. Потому что enabledRemoteNotificationTypes устарел с iOS 8 и выше. Для iOS 8 и более поздних версий вам необходимо использовать isRegisteredForRemoteNotifications .
Это 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")
}
}
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
Вот как это сделать в 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.
В Xamarin все вышеупомянутое решение не работает для меня. Вот что я использую вместо этого:
public static bool IsRemoteNotificationsEnabled() {
return UIApplication.SharedApplication.CurrentUserNotificationSettings.Types != UIUserNotificationType.None;
}
Он получает живое обновление также после того, как вы изменили статус уведомления в настройках.
Полностью легкое копирование и вставка кода, созданного на основе решения @ 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!