我正在寻找一种方法来确定用户是否有,通过设置,启用或禁用他们的推送通知我的应用程序。
调用enabledremotenotificationsttypes并检查掩码。
例如:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
// blah blah blah
iOS8及以上:
[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
quantumpotato的问题:
类型是由
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
可以使用
if (types & UIRemoteNotificationTypeAlert)
而不是
if (types == UIRemoteNotificationTypeNone)
将允许你只检查通知是否启用(不用担心声音,徽章,通知中心等)。第一行代码(types & UIRemoteNotificationTypeAlert)如果“Alert Style”设置为“横幅”或“警报”将返回YES,如果“Alert Style”设置为“None”则返回NO,与其他设置无关。
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
为了完成这个答案,它可以这样工作……
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;
}
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
// blah blah blah
{
NSLog(@"Notification Enabled");
}
else
{
NSLog(@"Notification not enabled");
}
这里我们从UIApplication获得UIRemoteNotificationType。它代表了这个应用程序在设置中的推送通知的状态,然后你可以很容易地检查它的类型
在最新版本的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;
}
尽管Zac的答案在iOS 7之前是完全正确的,但自从iOS 8到来后,它就发生了变化。因为enabledRemoteNotificationTypes从iOS 8开始就已经弃用了。对于iOS 8和更高版本,你需要使用isregisteredforremotenotifizations。
—>使用enabledRemoteNotificationTypes >使用isregisteredforremotenotifizations。
在iOS7和之前,你应该使用enabledRemoteNotificationTypes并检查它是否等于(或不等于取决于你想要什么)UIRemoteNotificationTypeNone。
然而,对于iOS8来说,仅仅检查isregisteredforremotenotifations并不总是足够的,因为上面有许多状态。你还应该检查application.currentUserNotificationSettings.types是否等于(或不等于取决于你想要什么)UIUserNotificationTypeNone!
isregisteredforremotenotifations可能返回true,即使currentUserNotificationSettings。types返回UIUserNotificationTypeNone。
下面是一个完整的例子,涵盖了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");
在尝试同时支持iOS8和更低版本时,我并没有像Kevin建议的那样使用isregisteredforremotenotifations。相反,我使用了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;
}
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
}
不幸的是,所提供的这些解决方案都没有真正解决问题,因为在提供相关信息时,api严重缺乏。你可以做一些猜测,但是使用currentUserNotificationSettings (iOS8+)在目前的形式下还不足以真正回答这个问题。虽然这里的许多解决方案似乎表明,要么是that,要么是isregisteredforremotenotification是一个更明确的答案,但实际上不是。
考虑一下:
with isregisteredforremotenotifations文档声明:
如果应用程序当前为远程通知注册,则返回YES,考虑到任何系统范围的设置…
However if you throw a simply NSLog into your app delegate to observe the behavior it is clear this does not behave the way we are anticipating it will work. It actually pertains directly to remote notifications having been activated for this app/device. Once activated for the first time this will always return YES. Even turning them off in settings (notifications) will still result in this returning YES this is because, as of iOS8, an app may register for remote notifications and even send to a device without the user having notifications enabled, they just may not do Alerts, Badges and Sound without the user turning that on. Silent notifications are a good example of something you may continue to do even with notifications turned off.
就currentUserNotificationSettings而言,它表示以下四件事之一:
警报开启 徽章都戴上了 声音开着 没有打开。
这完全没有给你任何关于其他因素或通知开关本身的指示。
事实上,用户可能会关闭徽章、声音和提醒,但仍然会在锁定屏幕或通知中心显示。该用户仍然可以收到推送通知,并且能够在锁定屏幕和通知中心看到它们。他们打开了通知开关。但是currentUserNotificationSettings会返回:UIUserNotificationTypeNone。这并不能真正反映用户的实际设置。
我们可以做一些猜测:
if isRegisteredForRemoteNotifications is NO then you can assume that this device has never successfully registered for remote notifications. after the first time of registering for remote notifications a callback to application:didRegisterUserNotificationSettings: is made containing user notification settings at this time since this is the first time a user has been registered the settings should indicate what the user selected in terms of the permission request. If the settings equate to anything other than: UIUserNotificationTypeNone then push permission was granted, otherwise it was declined. The reason for this is that from the moment you begin the remote registration process the user only has the ability to accept or decline, with the initial settings of an acceptance being the settings you setup during the registration process.
完全容易复制和粘贴代码构建从@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 !
斯威夫特 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()
}
}
}
这个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
下面是如何在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方法。
iOS8+ (OBJECTIVE 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;
}
}];
在Xamarin,以上所有的解决方案都不适合我。 这是我用的:
public static bool IsRemoteNotificationsEnabled() {
return UIApplication.SharedApplication.CurrentUserNotificationSettings.Types != UIUserNotificationType.None;
}
当你在设置中更改通知状态后,它也会得到实时更新。
我尝试使用@Shaheen ghassy提供的解决方案支持iOS 10及以上版本,但发现剥夺问题enabledRemoteNotificationTypes。所以,我找到的解决方案是使用isregisteredforremotenotification而不是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";
希望它也能帮助到其他人:) 快乐的编码。
推荐文章
- 在iPhone上确定用户是否启用了推送通知
- 是否有可能禁用浮动头在UITableView与UITableViewStylePlain?
- 错误ITMS-9000:“冗余二进制文件上传。火车1.0版本已经有一个二进制版本上传。
- Swift -转换为绝对值
- 从父iOS访问容器视图控制器
- 自定义dealloc和ARC (Objective-C)
- 调整UITableView的大小以适应内容
- 在代码中为UIButton设置一个图像
- NSRange从Swift Range?
- UICollectionView中的单元格间距
- 我如何在我的iOS应用程序中每n分钟得到一个后台位置更新?
- 如何使用iOS创建GUID/UUID
- 禁用所呈现视图控制器的交互式撤销
- 点击按钮时如何打开手机设置?
- 如何使用UIVisualEffectView来模糊图像?