一、推送的分类
-
本地推送通知
“本地”可以理解为”不联网”;即使没有网络情况下,也可以推送通知消息
通知发送方: 开发人员负责在APP内发送
应用场景: 确定知道未来某个时间点应该提醒用户什么 -
远程推送通知
与“本地”相对,表示,必须在联网情况下才会向用户推送通知消息
远程推送服务,又称为APNs(Apple Push Notification Services)
通知发送方: 服务器
应用场景:
- 不确定未来某个时间点应该提醒用户什么,临时性的
- 当APP彻底退出时也想继续让用户获取一些最新消息
二、注册推送
使用推送前你必须注册设置推送的形式,注册后系统才会弹出使用本地通知的权限弹框。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#ios8-ios10
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
return YES;
}
三、ios8-ios10
注意:如果当前程序正运行在前台,那么推送通知就不会被呈现出来
调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)
[[UIApplication sharedApplication] scheduleLocalNotification:ln];
取消调度本地推送通知
- (void)cancelLocalNotification:(UILocalNotification *)notification;
- (void)cancelAllLocalNotifications;
立即发出本地推送通知
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;
3.1、本地通知
- (IBAction)fireLocalNote:(id)sender {
// 1.创建本地通知
UILocalNotification *localNote = [[UILocalNotification alloc] init];
// 2.设置本地通知的内容
// 2.1.设置通知发出的时间
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0];
// 2.2.设置通知的内容
localNote.alertBody = @"吃饭了吗?";
// 2.3.设置滑块的文字
localNote.alertAction = @"快点";
// 2.4.决定alertAction是否生效
localNote.hasAction = NO;
// 2.5.设置点击通知的启动图片
localNote.alertLaunchImage = @"3213432dasf";
// 2.6.设置alertTitle
localNote.alertTitle = @"3333333333";
// 2.7.设置有通知时的音效
localNote.soundName = @"buyao.wav";
// 2.8.设置应用程序图标右上角的数字
localNote.applicationIconBadgeNumber = 999;
// 2.9.设置额外信息
localNote.userInfo = @{@"type" : @1};
// 3.调用通知
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
}
#pragma mark- 接收到本地通知时调用
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
// 当后台收到消息时,点击消息进行界面跳转
if (application.applicationState == UIApplicationStateInactive) {
NSLog(@"进行界面的跳转");
NSLog(@"%@", notification.userInfo);
UIView *redView = [[UIView alloc] init];
redView.frame = CGRectMake(0, 0, 100, 100);
redView.backgroundColor = [UIColor yellowColor];
[self.window.rootViewController.view addSubview:redView];
}
}
- 1、前台接收消息时调用
- 2、后台在接收到消息时,点击消息进入前台时调用。
- 3、程序杀死后,接收到消息时不会调用。
针对应用程序被杀死的情况我们可以这样处理
if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
// 跳转代码
UILabel *redView = [[UILabel alloc] init];
redView.frame = CGRectMake(0, 0, 200, 300);
redView.numberOfLines = 0;
redView.font = [UIFont systemFontOfSize:12.0];
redView.backgroundColor = [UIColor redColor];
redView.text = [NSString stringWithFormat:@"%@", launchOptions];
[self.window.rootViewController.view addSubview:redView];
}
3.2、远程通知
3.2.1、获取DeviceToken
1、当得到苹果的APNs服务器返回的DeviceToken就会被调用
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"deviceToken是:%@", deviceToken);
}
2、 当接收到远程通知时调用, iOS3.0之后有效
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(@"-2--%@", userInfo);
// [self.window.rootViewController.view addSubview:[[UISwitch alloc] init]]; // 测试app退出是否执行代码
}
- 当前在前台时; 或者app在后台状态下,点击通知打开app进入前台; 都可以执行这个方法
3、 当接收到远程通知时调用, iOS7.0之后有效
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(@"---%@", userInfo);
[self.window.rootViewController.view addSubview:[[UISwitch alloc] init]]; // 测试app退出是否执行代码
completionHandler(UIBackgroundFetchResultNewData);
}
- 当前在前台时; 或者app在后台、或者甚至app被杀死,点击通知打开app进入前台; 都可以执行这个方法
- 如果实现了这个方法那么上面(2)那个方法就不会执行
3.2.2、普通推送和静默推送
- 普通推送:就是常见的带有alter或者声音等的推送
- 静默推送: 就是用户无感知的推送,完全没有声音和文字。
普通推送和静默推送都是执行下面这个方法,区别在于:
1、静默推送,不用点开通知,不用打开APP,就能执行下面这个方法
2、普通推送和静默推送的内容格式不同
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[vc loadDataWithContentID:contentId completion:^(NSArray *dataList) {
vc.dataList = dataList;
NSLog(@"刷新数据结束");
completionHandler(UIBackgroundFetchResultNewData);
}];
}
- 1、 执行completionHandler的作用: 系统会估量App消耗的电量,并根据传递的UIBackgroundFetchResult 参数记录新数据是否可用;调用完成的处理代码时,应用的界面缩略图会自动更新
- 2、如果想实现静默推送的效果:
a、必须选后台模式Remote Notification;
b、告诉系统是否有新的内容更新(执行完成代码块)
c、设置发送通知的格式("content-available”:1) - 3、我们最多有30s的时间来处理数据,例如上面接收到远程通知到执行完网络请求之间的时间不能超过30秒
四、ios10及之后的推送(UserNotification)
4.1、新的注册方式
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(@"注册失败");
}
4.2、UNNotificationTrigger
苹果把本地通知跟远程通知合二为一,主要用UNNotificationTrigger这个类进行区分
- 1、UNPushNotificationTrigger(远程通知) 远程推送的通知类型
- 2、UNTimeIntervalNotificationTrigger (本地通知) 一定时间之后,重复或者不重复推送通知。我们可以设置timeInterval(时间间隔)和repeats(是否重复)。
- 3、UNCalendarNotificationTrigger(本地通知) 一定日期之后,重复或者不重复推送通知 例如,你每天8点推送一个通知,只要dateComponents为8,如果你想每天8点都推送这个通知,只要repeats为YES就可以了。
- 4、UNLocationNotificationTrigger (本地通知)地理位置的一种通知,当用户进入或离开一个地理区域来通知。
4.3、创建一个本地通知
UNTimeIntervalNotificationTrigger *timeTrigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:6.0f repeats:NO];
// 创建通知内容 UNMutableNotificationContent, 注意不是 UNNotificationContent ,此对象为不可变对象。
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"Dely 时间提醒 - title";
content.subtitle = [NSString stringWithFormat:@"Dely 装逼大会竞选时间提醒 - subtitle"];
content.body = @"Dely 装逼大会总决赛时间到,欢迎你参加总决赛!希望你一统X界 - body";
content.badge = @666;
content.sound = [UNNotificationSound defaultSound];
content.userInfo = @{@"key1":@"value1",@"key2":@"value2"};
// 创建通知标示
NSString *requestIdentifier = @"Dely.X.time";
// 创建通知请求 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) {
dispatch_async(dispatch_get_main_queue(), ^{
});
}
}];
4.4、对通知消息的接收和点击
ios10之前对通知消息的接收和点击都是通过-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
进行处理的,ios10之后分别用了两个代理方法进行处理:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
和- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
4.4.1、监听通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSDictionary * userInfo = notification.request.content.userInfo;
UNNotificationRequest *request = notification.request; // 收到推送的请求
UNNotificationContent *content = request.content; // 收到推送的消息内容
NSNumber *badge = content.badge; // 推送消息的角标
NSString *body = content.body; // 推送消息体
UNNotificationSound *sound = content.sound; // 推送消息的声音
NSString *subtitle = content.subtitle; // 推送消息的副标题
NSString *title = content.title; // 推送消息的标题
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"远程通知");
}else {
NSLog(@"本地通知");
}
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
}
- 1、只有当app处于前台状态时,接收到远程推送或者本地推送才会调用;当app处于后台模式时是不会调用的;
- 2、completionHandler的回调意味着消息通知可以在前台显示(ios10之前,如果当前程序正运行在前台,那么推送通知就不会被呈现出来)
- 3、本地通知和远程的通知的监听都是用同一个代理方法
4.4.2、通知的点击
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
//收到推送的请求
UNNotificationRequest *request = response.notification.request;
//收到推送的内容
UNNotificationContent *content = request.content;
//收到用户的基本信息
NSDictionary *userInfo = content.userInfo;
//收到推送消息的角标
NSNumber *badge = content.badge;
//收到推送消息body
NSString *body = content.body;
//推送消息的声音
UNNotificationSound *sound = content.sound;
// 推送消息的副标题
NSString *subtitle = content.subtitle;
// 推送消息的标题
NSString *title = content.title;
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"远程通知");
}else {
NSLog(@"本地通知");
}
completionHandler();
}
- 1、app在前台、后台、杀死状态下收到消息,点击消息时都会调用
- 2、completionHandler()必须调用,系统要求要不然控制台会报错
- 3、本地通知和远程通知的监听都是使用这个方法
4.4.3、静默推送
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
}
- 在使用了UserNotification做推送时,这个方法只有在静默推送时才会被调用。
网友评论