這兩天在做推送相關的功能,發現iOS10以后推送的變化還是很大的。在這里記錄下來,以供日后參考。
本文將以對比的形式來闡述iOS10本地推送的新特性。
準備工作
以下是判斷系統版本的宏定義,在后面要經常用到
#define IOS10_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0)
#define IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0)
#define IOS8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
#define IOS7_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
一、推送注冊
iOS10以前
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
iOS10以后
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = delegate;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@"注冊推送成功");
// 獲取注冊詳情
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"注冊詳情-%@", settings);
}];
} else {
NSLog(@"注冊推送失敗");
if (error) {
NSLog(@"失敗詳情-%@",error.description);
}
}
}];
用戶同意推送通知以后,獲取設備DeviceToken的方法沒有變
// 注冊獲得device Token
[application registerForRemoteNotifications];
Appdelegate中會獲得DeviceToken的回調
// 獲得Device Token
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *deviceString = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
deviceString = [deviceString stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"%@", [NSString stringWithFormat:@"設備Token: %@", deviceString]);
}
// 獲得Device Token失敗
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"注冊遠程推送(獲取Token)失敗: %@", error);
}
之后就可以對用戶進行推送了。
二、本地推送
iOS10以前
+ (void)creatLocalNotificationWithTitle:(NSString *)title subTitle:(NSString *)subTitle body:(NSString *)body userInfo:(NSDictionary *)userInfo fireDate:(NSDate *)fireDate repeatInterval:(NSCalendarUnit)repeatInterval {
UILocalNotification *notification = [[UILocalNotification alloc] init];
// 設置觸發通知的時間
notification.fireDate = fireDate;
// 時區
notification.timeZone = [NSTimeZone defaultTimeZone];
// 設置重復的間隔 iOS10以下無法基于自定義的時間重復,只能根據有限的枚舉進行重復NSCalendarUnit
notification.repeatInterval = repeatInterval;
// 通知內容
notification.alertBody = body;
notification.applicationIconBadgeNumber = 1;
// 通知被觸發時播放的聲音
notification.soundName = UILocalNotificationDefaultSoundName;
// 通知參數
notification.userInfo = userInfo;
// 執行通知注冊
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
iOS10以后分為了兩種Trigger來創建一個本地通知
1.iOS10基于時間間隔,創建一個本地通知
+ (void)creatLocalNotificationWithTitle:(NSString *)title subTitle:(NSString *)subTitle body:(NSString *)body userInfo:(NSDictionary *)userInfo requestIdentifier:(NSString *)requestIdentifier afterTimeInterval:(NSTimeInterval)timeInterval repeats:(BOOL)repeats {
// 設置觸發條件 UNTimeIntervalNotificationTrigger
UNTimeIntervalNotificationTrigger *timeTrigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:timeInterval repeats:repeats];
// 創建通知內容 UNMutableNotificationContent, 注意不是 UNNotificationContent ,此對象為不可變對象。
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = title;
content.subtitle = subTitle;
content.body = body;
content.badge = @1;
content.sound = [UNNotificationSound defaultSound];
content.userInfo = userInfo;
// 創建通知請求 UNNotificationRequest 將觸發條件和通知內容添加到請求中
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier content:content trigger:timeTrigger];
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 將通知請求 add 到 UNUserNotificationCenter
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"推送已添加成功 %@", requestIdentifier);
}
}];
}
2.iOS基于日歷時間,創建一個本地通知
+ (void)creatLocalNotificationWithTitle:(NSString *)title subTitle:(NSString *)subTitle body:(NSString *)body userInfo:(NSDictionary *)userInfo requestIdentifier:(NSString *)requestIdentifier dateComponents:(NSDateComponents *)components repeats:(BOOL)repeats {
// 設置觸發條件 UNNotificationTrigger
UNCalendarNotificationTrigger *timeTrigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:repeats];
// 創建通知內容 UNMutableNotificationContent, 注意不是 UNNotificationContent ,此對象為不可變對象。
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = title;
content.subtitle = subTitle;
content.body = body;
content.badge = @1;
content.sound = [UNNotificationSound defaultSound];
content.userInfo = userInfo;
// 創建通知請求 UNNotificationRequest 將觸發條件和通知內容添加到請求中
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier content:content trigger:timeTrigger];
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 將通知請求 add 到 UNUserNotificationCenter
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"推送已添加成功 %@", requestIdentifier);
}
}];
}
這里在附上一個關于NSDateComponents類型的常用表達
/**
* 關于NSDateComponents類型
* components.month = 7; 表示7月
* components.weekOfMonth = 4; 表示7月第四周(標準從周日~周六是一周)
* components.weekday = 2; 表示每周第二天
* components.hour = 13; 表示下午1點
* components.minute = 52; 表示52分鐘
* 設置repeats=YES時,系統會按照如上規則進行重復提醒,缺省值忽略
*/
下面來說一下如何刪除或修改一個本地推送
iOS10以前
// 刪除某個指定通知
// 首先獲取所有通知
NSArray *notificaitons = [[UIApplication sharedApplication] scheduledLocalNotifications];
if (!notificaitons || notificaitons.count <= 0) {
return;
}
for (UILocalNotification *notify in notificaitons) {
// 這里的requestIdentifier是保存在userInfo當中的一個自己定義的字段,用來區分每個通知,每次刪除或修改都需要從所有的通知中進行遍歷,感覺很麻煩,iOS10就不用這樣了
if ([[notify.userInfo objectForKey:@"requestIdentifier"] isEqualToString:requestIdentifier]) {
// 取消一個特定的通知
[[UIApplication sharedApplication] cancelLocalNotification:notify];
break;
}
}
// 刪除所有通知
[[UIApplication sharedApplication] cancelAllLocalNotifications];
iOS10以后
// 刪除某個指定通知
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// iOS10以后,requestIdentifier就變成了通知本身的一個屬性,可以通過系統提供的方法進行查詢獲取,不用再遍歷所有的通知了,方便了很多。修改通知只要創建一個同樣requestIdentifier的通知覆蓋原通知即可。
[center removePendingNotificationRequestsWithIdentifiers:@[requestIdentifier]];
[center removeDeliveredNotificationsWithIdentifiers:@[requestIdentifier]];
// 刪除所有通知
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center removeAllPendingNotificationRequests];
[center removeAllDeliveredNotifications];
以上只是最基本的添加和刪除操作,第二篇會詳說關于通知的樣式,Action的添加操作。