前段时间接手到一个关于本地推送的活,还可以设置重复本地推送,把此次记录拆分成两篇,第一篇主要是记录推送的设置,第二篇主要来讲一下如何实现重复推送。
iOS 本地推送开发记录二
初始化推送设置(项目支持最低iOS8.0)
头文件导入,需要增加版本的判断
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import
#endif
由于涉及到iOS版本的兼容,需要考虑iOS10以下及iOS8以上的设置
if (@available(iOS 10.0, *)) {
//iOS10特有
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 必须写代理,不然无法监听通知的接收与点击
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// 点击允许
NSLog(@"注册成功");
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"%@", settings);
}];
} else {
// 点击不允许
NSLog(@"注册失败");
}
}];
} else {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
推送的设置
if (@available(iOS 10.0, *)) {
// 使用 UNUserNotificationCenter 来管理通知
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
//需创建一个包含待通知内容的 UNMutableNotificationContent 对象,注意不是 UNNotificationContent ,此对象为不可变对象。
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = title;
content.body = body;
UNNotificationSound *sound = [UNNotificationSound soundNamed:soundName];
content.sound = sound;
content.userInfo = param;
// 在 alertTime 后推送本地推送
UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger
triggerWithTimeInterval:timeInterval repeats:NO];
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:notificationId
content:content trigger:trigger];
//添加推送成功后的处理!
[center addNotificationRequest:request withCompletionHandler:nil];
} else {
NSDate *fireDate = nil;
if (time > 0) {
// 定时时间存在,以定时时间为准
fireDate = [NSDate dateWithTimeIntervalSinceNow:time];
} else {
fireDate = [NSDate dateWithTimeIntervalSince1970:dateTime];
}
// 1.创建通知
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
// 2.设置通知
// 设置通知标题
if (@available(iOS 8.2, *)) {
localNotification.alertTitle = title ? title : @"";
}
// 设置通知显示的内容
localNotification.alertBody = body ? body : @"";
// 设置通知的发送时间,单位秒
localNotification.fireDate = fireDate;
//收到通知时App icon的角标
localNotification.applicationIconBadgeNumber = 1;
//推送是带的声音提醒,设置默认的字段为UILocalNotificationDefaultSoundName
localNotification.soundName = soundName;
// 3.发送通知
// 方式一: 根据通知的发送时间(fireDate)发送通知
NSMutableDictionary *newParam = [NSMutableDictionary dictionaryWithDictionary:param];
newParam[@"identifier"] = notificationId;
localNotification.userInfo = newParam;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
推送的处理
在接收到推送的处理方式上,iOS8和iOS10上有所不同
iOS8上需要通过UIApplicationDelegate的代理方法如下:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
NSLog(@"notification:%@", notification);
}
iOS10上需要通过UNUserNotificationCenterDelegate相关代理方法,iOS10上在应用内收到推送时,可以通过willPresentNotification这个代理方法里面通过completionHandler(0)关闭推送的展示
//在展示通知前进行处理,即有机会在展示通知前再修改通知内容。
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler API_AVAILABLE(ios(10.0)){
if (@available(iOS 10.0, *)) {
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS10 收到远程通知:%@", notification);
}
else {
NSLog(@"iOS10 收到本地通知:%@", notification);
}
}
// 避免APP打开的状态下在iOS10+下出现本地推送
completionHandler(0);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)){
if (@available(iOS 10.0, *)) {
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS10 收到远程通知:%@", response);
}
else {
NSLog(@"iOS10 收到本地通知:%@", response);
}
}
}
推送的更新
iOS8上通过注册时添加一个identifier,在更新时找到这个identifier的推送,并取消,然后重新注册推送即可实现更新。
iOS10上因为有identifier的存在,所以可以直接复用之前的identifier可以更新成最新的推送
if (@available(iOS 10.0, *)) {
// iOS10+ 只要重新设置一次 就能完成更新
} else {
// 获取所有本地通知数组
NSArray *localNotifications = [UIApplication sharedApplication].scheduledLocalNotifications;
for (UILocalNotification *notification in localNotifications)
{
NSDictionary *userInfo = notification.userInfo;
if (userInfo)
{
NSString *identifier = [self getNoticeIdentifierWithId:param[@"id"]];
// 如果找到需要取消的通知,则取消
if ([identifier isEqualToString:userInfo[@"identifier"]]) {
[[UIApplication sharedApplication] cancelLocalNotification:notification];
break;
}
}
}
}
推送的删除
iOS8和iOS10上思路都是通过一个identifier来找到之前的推送分别调用自己的取消方法即可,所以如果涉及到修改、删除推送的操作,identifier的设置很重要。
if (@available(iOS 10.0, *)) {
[[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[identifier]];
} else {
// 获取所有本地通知数组
NSArray *localNotifications = [UIApplication sharedApplication].scheduledLocalNotifications;
for (UILocalNotification *notification in localNotifications)
{
NSDictionary *userInfo = notification.userInfo;
if (userInfo)
{
// 如果找到需要取消的通知,则取消
if ([identifier isEqualToString:userInfo[@"identifier"]]) {
[[UIApplication sharedApplication] cancelLocalNotification:notification];
break;
}
}
}
}