前言
随着智能手机设备的普及,好多APP都用到了推送服务,而iOS下应用分为两种不同的Notification种类。本地推送和远程推送。本地推送是由iOS下的NotificationManage进行统一管理的,只需要将封装好的本地Notification对象加入到系统的Notification管理中去即可。而远程推送需要服务器的支持并且处于长连接的状态,通常用来定时提醒用户完成一些任务或参加一些活动。
本地通知的实现
NSObject+NSLocalNotification.h
#import <Foundation/Foundation.h>
@interface NSObject (NSLocalNotification)
/**
* 注册通知 为NSObject 扩展本地通知的分类
*
* @param time 距离当前时间为多少秒发送通知
* @param content 推送通知的内容
* @param key 注册通知的key值
*/
+ (void)registerLocalNotification:(NSInteger)time content:(NSString *)content key:(NSString *)key;
/**
* 取消通知
*
* @param key 根据key值取消对应通知
*
*/
+ (void)cancelLocalNotificationWithKey:(NSString *)key;
@end ```
###1. 注册通知,配置相应的参数
NSObject+NSLocalNotification.m
```ruby
#define DEVICE_iOS_8 [UIDevice currentDevice].systemVersion.floatValue >= 8.0
#define DEVICE_iOS_9 [UIDevice currentDevice].systemVersion.floatValue >= 9.0
#import "NSObject+NSLocalNotification.h"
#import "AppDelegate.h"
@implementation NSObject (NSLocalNotification)
+ (void)registerLocalNotification:(NSInteger)time content:(NSString *)content key:(NSString *)key;
{
//创建一个本地通知
UILocalNotification *notification = [[UILocalNotification alloc] init];
// 设置触发通知的时间
NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:time];
notification.fireDate = fireDate;
// 时区
notification.timeZone = [NSTimeZone defaultTimeZone];
// 设置重复的间隔
notification.repeatInterval = 0;
notification.alertBody = content;
notification.applicationIconBadgeNumber = 1;
notification.soundName = UILocalNotificationDefaultSoundName;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:content forKey:key];
notification.userInfo = userDict;
//请求本地通知 授权
[self getRequestWithLocalNotificationSleep:notification];
//选择使用 哪个操作组(这个操作组可以自定义 比如QQ消息从顶部弹出消息后可以自定义设置Action 例如 :快捷回复 关闭等)
// notification.category = @"select";
} ```
###2.请求授权
``` ruby
- (void)getRequestWithLocalNotificationSleep:(UILocalNotification *)notification
{
// ios8后,需要添加这个注册,才能得到授权
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
#warning 注册完之后如果不删除,下次会继续存在,即使从模拟器卸载掉也会保留
[[UIApplication sharedApplication]cancelAllLocalNotifications];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
#pragma mark - 取消通知
+ (void)cancelLocalNotificationWithKey:(NSString *)key
{
// 获取所有本地通知数组
NSArray *localNotifications = [UIApplication sharedApplication].scheduledLocalNotifications;
if (localNotifications) {
for (UILocalNotification *notification in localNotifications) {
NSDictionary *userInfo = notification.userInfo;
if (userInfo) {
// 根据设置通知参数时指定的key来获取通知参数
NSString *info = userInfo[key];
// 如果找到需要取消的通知,则取消
if ([info isEqualToString:key]) {
if (notification) {
[[UIApplication sharedApplication] cancelLocalNotification:notification];
}
break;
}
}
}
}
}
3.调用通知
Appdelegate.m
#define LOCALNOTIFICATION_KEY @"localNotificationKey"
#import "AppDelegate.h"
#import "NSObject+NSLocalNotification.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[AppDelegate registerLocalNotification:10 content:@"本地推送练习" key:LOCALNOTIFICATION_KEY];
NSLog(@"launchOptions: %@", launchOptions);
return YES;
}```
###4.接收到通知后的回调
/**
只有当发送出一个本地通知, 并且满足以下条件时, 才会调用该方法
APP 处于前台情况
当用用户点击了通知, 从后台, 进入到前台时,
当锁屏状态下, 用户点击了通知, 从后台进入前台
注意: 当App彻底退出时, 用户点击通知, 打开APP , 不会调用这个方法
但是会把通知的参数传递给 application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:
*/
-
(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"接收到本地通知" message:notification.alertBody delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];// 查看当前的状态出于(前台: 0)/(后台: 2)/(从后台进入前台: 1)
NSLog(@"applicationState.rawValue: %zd", application.applicationState);// 执行响应操作
// 如果当前App在前台,执行操作
if (application.applicationState == UIApplicationStateActive) {
NSLog(@"执行前台对应的操作");
} else if (application.applicationState == UIApplicationStateInactive) {
// 后台进入前台
NSLog(@"执行后台进入前台对应的操作");
NSLog(@"*****%@", notification.userInfo);
} else if (application.applicationState == UIApplicationStateBackground) {
// 当前App在后台NSLog(@"执行后台对应的操作");
}
}```
- 至此 一个本地推送已经完成 需要注意的是
- app处于前台 此时不会弹框通知用户通知的到达,但是还是会调用对应的代理方法
- app并没有关闭,一直隐藏在后台时此时用户点击通知信息后,会让app进入前台,并会调用AppDelegate的下面方法
application: didReceiveLocalNotification:
- app已经被关闭(进程已死)此时用户点击通知信息后,会启动app,启动完毕会调用AppDelegate的下面方法
application:didFinishLaunchingWithOptions:launchOptions
参数通过UIApplicationLaunchOptionsLocalNotificationKey
取出本地推送通知象- 如果本地通知没有移除,就算是卸载了app后,下次重新安装还是会存在
- 本地通知经过查阅资料有数量限制。貌似是64个以内。超过的将被系统忽略
关于带有Action的本地通知,详情见本文demo地址 https://github.com/JimmyLession/NSLocalNotificationDemo.git
如有任何疑问可以私信,谢谢!