这两天在做推送相关的功能,发现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的添加操作。