最近在做一個(gè)關(guān)于UNUserNotification通知的需求叛复,需要獲取當(dāng)前APP的通知權(quán)限仔引,由于iOS10以上通知使用的API發(fā)生了很大的變化扔仓,在iOS 10以下獲取通知設(shè)置(notification settings)代碼如下:
UIUserNotificationSettings *theSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
return [theSettings types] & UIUserNotificationTypeAlert;
?而 iOS10采用UNUserNotificationCenter代替了原有的API。使用UNUserNotificationCenter獲取APP通知設(shè)置代碼如下:
UNUserNotificationCenter *notificationCenter=[UNUserNotificationCenter currentNotificationCenter];
[notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
switch (settings.authorizationStatus) {
case UNAuthorizationStatusAuthorized:
enabled = YES;
break;
default:
break;
}
}];
getNotificationSettingsWithCompletionHandler:
采用的是異步回調(diào)的過程咖耘。為了寫一個(gè)兼容兩種類型的函數(shù)翘簇,我的代碼如下:
__block BOOL enabled = NO;
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *notificationCenter=[UNUserNotificationCenter currentNotificationCenter];
[notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
switch (settings.authorizationStatus) {
case UNAuthorizationStatusAuthorized:
enabled = YES;
break;
default:
break;
}
}];
} else {
UIApplication *application = [UIApplication sharedApplication];
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
UIUserNotificationSettings *settings = [application currentUserNotificationSettings];
if (settings.types != UIUserNotificationTypeNone) {
enabled = YES;
}
}
}
這樣貌似很完美,其實(shí)這段代碼犯了一個(gè)很低級(jí)的錯(cuò)誤鲤看。把異步當(dāng)成同步再用缘揪。當(dāng)時(shí)發(fā)現(xiàn)這個(gè)問題時(shí),APP已經(jīng)上線了义桂,最后只好向領(lǐng)導(dǎo)老實(shí)認(rèn)錯(cuò)寫檢討找筝。傷心太平洋(πーπ)
出現(xiàn)錯(cuò)誤肯定要改嘛,最后想到了用信號(hào)量來強(qiáng)制將異步變?yōu)橥娇兜酰暮蟮拇a如下:
__block BOOL enabled = NO;
if (@available(iOS 10.0, *)) {
dispatch_semaphore_t sem;
sem = dispatch_semaphore_create(0);
UNUserNotificationCenter *notificationCenter=[UNUserNotificationCenter currentNotificationCenter];
[notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
switch (settings.authorizationStatus) {
case UNAuthorizationStatusAuthorized:
enabled = YES;
break;
default:
break;
}
dispatch_semaphore_signal(sem);
}];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); //獲取通知設(shè)置的過程是異步的袖裕,這里需要等待
} else {
UIApplication *application = [UIApplication sharedApplication];
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
UIUserNotificationSettings *settings = [application currentUserNotificationSettings];
if (settings.types != UIUserNotificationTypeNone) {
enabled = YES;
}
}
}
另附上Stack Overflow一個(gè)獲取Notification Settings通用的類,
地址
.h文件
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger , PushNotificationType) {
PushNotificationTypeNone = 0, // the application may not present any UI upon a notification being received
PushNotificationTypeBadge = 1 << 0, // the application may badge its icon upon a notification being received
PushNotificationTypeSound = 1 << 1, // the application may play a sound upon a notification being received
PushNotificationTypeAlert = 1 << 2, // the application may display an alert upon a notification being received
};
@interface SpecificPush : NSObject
@property (nonatomic, readonly) PushNotificationType currentNotificationSettings;
+ (SpecificPush *)sharedInstance;
- (PushNotificationType)types;
@end
.m文件
#import <UserNotifications/UserNotifications.h>
@interface SpecificPush()
@property (nonatomic) PushNotificationType currentNotificationSettings;
@end
@implementation SpecificPush
#pragma mark - Init
static SpecificPush *instance = nil;
+ (SpecificPush *)sharedInstance
{
@synchronized (self)
{
if (instance == nil)
{
[SpecificPush new];
}
}
return instance;
}
- (instancetype)init
{
NSAssert(!instance, @"WARNING - Instance of SpecifishPush already exists");
self = [super init];
if (self)
{
self.currentNotificationSettings = PushNotificationTypeNone;
}
instance = self;
return self;
}
- (PushNotificationType)types
{
if (@available(iOS 10.0, *))
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings) {
if ((settings.soundSetting == UNNotificationSettingDisabled) && (settings.alertSetting == UNNotificationSettingDisabled) && (settings.soundSetting == UNNotificationSettingDisabled))
{
self.currentNotificationSettings = PushNotificationTypeNone;
}
if (settings.badgeSetting == UNNotificationSettingEnabled)
{
self.currentNotificationSettings = PushNotificationTypeBadge;
}
if (settings.soundSetting == UNNotificationSettingEnabled)
{
self.currentNotificationSettings = PushNotificationTypeSound;
}
if (settings.alertStyle == UNNotificationSettingEnabled)
{
self.currentNotificationSettings = PushNotificationTypeAlert;
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(semaphore);
}
else
{
UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (settings.types == UIUserNotificationTypeNone)
{
self.currentNotificationSettings = PushNotificationTypeNone;
}
if (settings.types & UIUserNotificationTypeBadge)
{
self.currentNotificationSettings = PushNotificationTypeBadge;
}
if (settings.types & UIUserNotificationTypeSound)
{
self.currentNotificationSettings = PushNotificationTypeSound;
}
if (settings.types & UIUserNotificationTypeAlert)
{
self.currentNotificationSettings = PushNotificationTypeAlert;
}
}
return self.currentNotificationSettings;
}
@end