前言
通知和推送
是应用程序中很重要的组成部分。本地通知
可以为应用程序注册一些定时任务,例如闹钟、定时提醒等。远程推送
则更强大,提供了一种通过服务端主动推送消息到客户端的方式,服务端可以更加灵活地控制通知逻辑,例如广告的推送、定时任务的提醒、即时通信类应用离线消息的提醒等。本文先着重着介绍本地通知,由于iOS系统的不断更新,本地通知的API也需要根据设备的系统来进行选择和兼容。
注:本地通知不需要连接网络,一般是开发人员在合适的情况下,在App内发送通知。
UILocalNotification
- 简介
ULLocalNotification
是 iOS8
中的一个类(In iOS 8.0 and later),用来实现本地通知功能。通知,实际上是由iOS系统管理的一个功能,比如注册了通知,则系统会在通知被触发时给应用程序发送消息。但是,ULLocalNotification仅能提供开发者去编辑消息,消息推送到app上展示的样式和交互则是固定的,开发者自定制的难度相当大。
- 添加步骤
- 创建通知对象
- 设置触发时间
- 设置通知属性
- 执行本地通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| // 推送本地通知 iOS 10.0 及以下 - (void)pushLocalNotificationIOS10AndBelowWithTime:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ // 1.创建通知对象 UILocalNotification * notification = [[UILocalNotification alloc] init]; // 2.设置触发通知的时间(几秒后发送) NSDate * fireDate = [NSDate dateWithTimeIntervalSinceNow:time]; notification.fireDate = fireDate; // 3.设置通知属性 // 通知标题 notification.alertTitle = title; // 通知主体 notification.alertBody = body; // 待机界面开启左滑按钮 notification.hasAction = YES; // 待机界面的滑动按钮提示 notification.alertAction = @"点击查看消息"; // 在收到通知时播放的声音,默认消息声音 notification.soundName = UILocalNotificationDefaultSoundName; // 设置启动屏 // notification.alertLaunchImage = @""; // 传递的用户数据 // notification.userInfo = @{}; // 图标的消息数 // notification.applicationIconBadgeNumber = 1; // 时区 // notification.timeZone = [NSTimeZone defaultTimeZone]; // 设置重复的间隔 // notification.repeatInterval = kCFCalendarUnitSecond; // 附加操作 // notification.category = @"choose"; // 4.执行本地通知 [[UIApplication sharedApplication] scheduleLocalNotification:notification]; }
|
立即执行本地通知用:
- 处理逻辑
1 2 3 4 5 6 7 8 9
| // 本地通知授权 - (void)localNotificationAuthorizationIOS10AndBelow{ // 如果已经得到授权,就直接添加本地通知,否则申请询问授权 if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) { // 开始授权 UIUserNotificationSettings * notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings]; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| // 推送本地通知 iOS 10.0 及以下 - (void)pushLocalNotificationIOS10AndBelowWithTime:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) { [SVPManager showWithStatus:@"请您在前往 设置->通用->零信任->通知->开启允许通知 权限,以便为您提供本地通知服务" time:2]; return; } // 1.创建通知对象 UILocalNotification * notification = [[UILocalNotification alloc] init]; // 2.设置触发通知的时间(几秒后发送) NSDate * fireDate = [NSDate dateWithTimeIntervalSinceNow:time]; notification.fireDate = fireDate; // 3.设置通知属性 // 通知标题 notification.alertTitle = title; // 通知主体 notification.alertBody = body; // 待机界面开启左滑按钮 notification.hasAction = YES; // 待机界面的滑动按钮提示 notification.alertAction = @"点击查看消息"; // 在收到通知时播放的声音,默认消息声音 notification.soundName = UILocalNotificationDefaultSoundName; // 设置启动屏 // notification.alertLaunchImage = @""; // 传递的用户数据 // notification.userInfo = @{}; // 图标的消息数 // notification.applicationIconBadgeNumber = 1; // 时区 // notification.timeZone = [NSTimeZone defaultTimeZone]; // 设置重复的间隔 // notification.repeatInterval = kCFCalendarUnitSecond; // 附加操作 // notification.category = @"choose"; // 4.执行本地通知 [[UIApplication sharedApplication] scheduleLocalNotification:notification]; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| /* App处于kill掉时,点击通知栏进入App,使用该方法接收本地(远程)通知 */ - (void)receiveLocalNotificationWithLaunchOptions:(NSDictionary *)launchOptions{ /* App被kill掉,通过通知启动App 1.本地的 key - UIApplicationLaunchOptionsLocalNotificationKey 2.远程的 key - UIApplicationLaunchOptionsRemoteNotificationKey */ if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) { UILocalNotification * notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; [self handleLocalNotificationWithWithNotification:notification userInfo:launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]]; } } // 处理本地通知 - (void)handleLocalNotificationWithWithNotification:(UILocalNotification *)notification userInfo:(NSDictionary *)userInfo{ NSLog(@"title:%@ body:%@",notification.alertTitle,notification.alertBody); }
|
AppDelegate下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #pragma mark - 接收本地通知 /* App处于挂起或运行时,调用该方法接收本地(远程)通知 1.当App在前台状态下,点击推送通知,会调用该方法 2.当App在后台状态下,点击推送通知,会调用该方法(从锁屏界面点击推送通知也会执行) */ - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{ NSLog(@"%@",notification); // 前台点击通知消息 if (application.applicationState == UIApplicationStateActive) { NSLog(@"处理前台接受通知的业务"); } // 后台点击通知消息 else { NSLog(@"处理后台台接受通知的业务"); [[LocalNotiManager sharedManager] handleLocalNotificationWithWithNotification:notification userInfo:notification.userInfo]; } } // 当用户点击允许或者不允许时,会执行如下代理方法,我们在其中实现处理逻辑 - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{ NSLog(@"当用户点击允许或者不允许时,会执行如下代理方法"); }
|
- 附加操作
可以添加附加操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| // 添加附加操作 - (void)addCategoryAction{ if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) { /* 推送通知的附加操作,可以为nil,此时只显示消息 如果不为nil,可以再推送消息的后面增加几个按钮(如同意、不同意) */ UIMutableUserNotificationCategory * category = [UIMutableUserNotificationCategory new]; category.identifier = @"choose"; // 同意 UIMutableUserNotificationAction * action1 = [UIMutableUserNotificationAction new]; action1.identifier = @"yes"; action1.title = @"同意"; // 点击按钮是否进入前台 action1.activationMode = UIUserNotificationActivationModeForeground; action1.authenticationRequired = true; action1.destructive = false; // 不同意 UIMutableUserNotificationAction * action2 = [UIMutableUserNotificationAction new]; action2.identifier = @"no"; action2.title = @"不同意"; // 后台模式 action2.activationMode = UIUserNotificationActivationModeBackground; action2.authenticationRequired = true; action2.destructive = true; if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) { action2.behavior = UIUserNotificationActionBehaviorTextInput; action2.parameters = @{UIUserNotificationTextInputActionButtonTitleKey:@"拒绝原因"}; } [category setActions:@[action1,action2] forContext:UIUserNotificationActionContextDefault]; NSSet<UIUserNotificationCategory *> * categorys = [NSSet setWithObjects:category, nil]; UIUserNotificationType type = UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound; UIUserNotificationSettings * settings = [UIUserNotificationSettings settingsForTypes:type categories:categorys]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; } }
|
UserNotification
- 简介
UserNotification
是iOS10后苹果提出的一个整合的通知和推送框架,对之前的通知和推送功能进行了全面的重构和优化,功能更强大,定制更灵活。表现如下:
- 通知处理代码从AppDelegate中剥离
- 通知的注册、设置、处理更加结构化,更易于进行模块的开发
- 支持自定义通知音效和启动图
- 支持向通知内容中添加媒体附件,例如音效、视频
- 支持开发者定义多套通知展示模块
- 支持完全自定义的通知界面
- 支持自定义通知中的用户交互按钮
- 通知的触发更加容易管理
- 核心类结构图
- UNNotificationCenter:通知管理中心单例设计,负责通知的注册、接收通知后的回调处理等,是UserNofitication框架的核心。
- UNNotification:通知对象,其中封装了通知请求
- UNNoticationSettings:通知相关设置
- UNNotificationCategory:通知模板
- UNNotificationAction:用于定义通知模板中的用户交互行为
- UNNotificationRequest:注册通知请求,其中定义了通知的内容和触发方式
- UNNotificationResponse:接收到通知后的回执
- UNNotificationContent:通知的具体内容
- UNNotificationAttachment:通知所携带的附件,为通知内容添加
- UNNotificationSound:定义通知音效, (音频文件必须位于bundle或者Library/Sounds目录下)
- UNNotificationTrigger:通知触发器,由其子类具体定义
- UNPushNotificationTrigger:远程推送触发器,UNNotificationTrigger的子类
- UNTimerInrevalNotificationTrigger:计时器触发器,UNNotificationTrigger的子类
- UNCalendarNotificationTrigger:周期日历触发器,UNNotificationTrigger的子类
- UNLocationNotificationTrigger:地域触发器,UNNotificationTrigger的子类
- UNNotificationCenterDelegate:协议,其中方法用于监听通知状态
注意:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| extern Nsstring *const UNNotificationAttachmentoptionsTypeHintkey: 配置附件的类型的键,NSString类型的值,如果不设置,则默认从扩展名推断
extern NSstring *const UNNotificationAttachmentoptionsThumbnailHiddenkey: 配置是否隐藏缩路图,配置NSNumber类型的值 0或者1
CGRectCreateDictionaryRepresentation(CGRect): 创建的矩形引用
extern NSString *cost UNNotificationAttachmentOptionsThumbnailClippingRectKey: 创建使用一个标准的矩形对缩略图进行裁剪
extern NSString *const UNNotificationAttachmentoptionsThumbnailTimekey: 使用视频中的某一帧作为缩略图,配置NSNumber类型的时间
|
- 权限申请 和 附件资源包位置(Bundle目录下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 本地通知授权 - (void)localNotificationAuthorizationIOS10AndAbove{ // 使用 UNUserNotificationCenter 来管理通知 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 设置通知中心的代理 center.delegate = self; // iOS 10.0使用以下方法注册,才能得到授权 [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) { // 用户是否同意 if (granted) { NSLog(@"用户同意授权"); }else { NSLog(@"用户不同意授权"); } }]; }
|
- 推送本地通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| // 推送本地通知 iOS 10.0 及以上 - (void)pushLocalNotificationIOS10AndAboveWithTime:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ // 1.创建通知管理类 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 2.设置通知内容 UNMutableNotificationContent * content = [[UNMutableNotificationContent alloc] init]; // 设置通知请求发送时App图标上显示的数字 // content.badge = @1; // 设置通知的标题 content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; // 设置通知的副标题 // content.subtitle = @""; // 设置通知的主体 content.body = [NSString localizedUserNotificationStringForKey:body arguments:nil]; // 设置通知的提示音 content.sound = [UNNotificationSound defaultSound]; // 设置从通知激活App时的launchImage图片 // content.launchImageName = @""; /* 3.设置触发器: 计时器触发 1.TimeInterval:时间间隔 2.repeats:是否重复*/ UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:repeats]; /* 设置触发器: 周期日历触发 */ // NSDateComponents * components = [[NSDateComponents alloc] init]; // components.year = 2023; // components.month = 11; // components.day = 2; // UNCalendarNotificationTrigger * trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:repeats]; /* 设置触发器:地域触发 */ // CLRegion * region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(33.0, 11.0) radius:100 identifier:@"region"]; // UNLocationNotificationTrigger * trigger = [UNLocationNotificationTrigger triggerWithRegion:region repeats:repeats]; /* 4.设置通知请求 1.Identifier:通知标识 2.content:通知内容 3.trigger:触发器 */ UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; // 5.添加通知请求 [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"添加推送通知失败"); }else { NSLog(@"添加推送通知成功"); } }]; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| // 推送本地通知 iOS 10.0 及以上(图片) - (void)pushLocalNotificationIOS10AndAboveWithTime:(int)time imgName:(NSString *)imgName title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ // 1.创建通知管理类 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 2.通知内容 UNMutableNotificationContent * content = [UNMutableNotificationContent new]; /* 设置图片附件 attachments:数组,但系统的通知模板只能展示其中一个附件,设置多个附件也不会有额外的效果 但是如果开发者自定义通知模板UI,此数组就派上用场了 */ NSString * path = [[NSBundle mainBundle] pathForResource:imgName ofType:nil]; NSURL * url = [NSURL fileURLWithPath:path]; UNNotificationAttachment * attachment = [UNNotificationAttachment attachmentWithIdentifier:identifier URL:url options:nil error:nil]; content.attachments = @[attachment]; // 设置通知的标题 content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; // 设置通知的副标题 // content.subtitle = @""; // 设置通知请求时发送时App图标上显示的数字 // content.badge = @1; // 设置通知的主体 content.body = body; // 设置通知提示音 content.sound = [UNNotificationSound defaultSound]; // 设置从通知激活App时的launchImage图片 // content.launchImageName = @""; /* 4.设置触发器: 计时器触发 1.TimeInterval:时间间隔 2.repeats:是否重复*/ UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:repeats]; /* 4.设置通知请求 1.Identifier:通知标识 2.content:通知内容 3.trigger:触发器 */ UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; // 5.添加通知请求 [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"添加推送通知失败"); }else { NSLog(@"添加推送通知成功"); } }]; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| // 推送本地通知 iOS 10.0 及以上(音频) - (void)pushLocalNotificationIOS10AndAboveWithAudioName:(NSString *)audioName time:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ // 1.创建通知管理类 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 2.通知内容 UNMutableNotificationContent * content = [UNMutableNotificationContent new]; /* 设置音频附件 attachments:数组,但系统的通知模板只能展示其中一个附件,设置多个附件也不会有额外的效果 但是如果开发者自定义通知模板UI,此数组就派上用场了 */ NSString * path = [[NSBundle mainBundle] pathForResource:audioName ofType:nil]; NSURL * url = [NSURL fileURLWithPath:path]; UNNotificationAttachment * attachment = [UNNotificationAttachment attachmentWithIdentifier:identifier URL:url options:nil error:nil]; content.attachments = @[attachment]; // 设置通知的标题 content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; // 设置通知的副标题 // content.subtitle = @""; // 设置通知请求时发送时App图标上显示的数字 // content.badge = @1; // 设置通知的主体 content.body = body; // 设置通知提示音 content.sound = [UNNotificationSound defaultSound]; // 设置从通知激活App时的launchImage图片 // content.launchImageName = @""; /* 4.设置触发器: 计时器触发 1.TimeInterval:时间间隔 2.repeats:是否重复*/ UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:repeats]; /* 4.设置通知请求 1.Identifier:通知标识 2.content:通知内容 3.trigger:触发器 */ UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; // 5.添加通知请求 [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"添加推送通知失败"); }else { NSLog(@"添加推送通知成功"); } }]; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| // 推送本地通知 iOS 10.0 及以上(视频) - (void)pushLocalNotificationIOS10AndAboveWithVideoName:(NSString *)videoName time:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ // 1.创建通知管理类 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 2.通知内容 UNMutableNotificationContent * content = [UNMutableNotificationContent new]; /* 设置音频附件 attachments:数组,但系统的通知模板只能展示其中一个附件,设置多个附件也不会有额外的效果 但是如果开发者自定义通知模板UI,此数组就派上用场了 */ NSString * path = [[NSBundle mainBundle] pathForResource:videoName ofType:nil]; NSURL * url = [NSURL fileURLWithPath:path]; UNNotificationAttachment * attachment = [UNNotificationAttachment attachmentWithIdentifier:identifier URL:url options:nil error:nil]; content.attachments = @[attachment]; // 设置通知的标题 content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; // 设置通知的副标题 // content.subtitle = @""; // 设置通知请求时发送时App图标上显示的数字 // content.badge = @1; // 设置通知的主体 content.body = body; // 设置通知提示音 content.sound = [UNNotificationSound defaultSound]; // 设置从通知激活App时的launchImage图片 // content.launchImageName = @""; /* 4.设置触发器: 计时器触发 1.TimeInterval:时间间隔 2.repeats:是否重复*/ UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:repeats]; /* 4.设置通知请求 1.Identifier:通知标识 2.content:通知内容 3.trigger:触发器 */ UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; // 5.添加通知请求 [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"添加推送通知失败"); }else { NSLog(@"添加推送通知成功"); } }]; }
|
- 效果
- 使用模板
除了上面介绍的强大的附件通知外,我们还可以把 UserNotification
提供的模板功能和用户行为利用起来。在iOS系统中,聊天类软件常常采用后台推送的方式推送消息,用户可以在不进入应用程序的情况下,直接在桌面回复通过通知推送过来的消息,这种功能就是通过 UNNotificationCategory
和 UNNotificationAction
用户行为来实现的。对于文本回复框,UserNotification
框架提供了 UNTextInputNotificationAction
类,也即 UNNotificationAction
的子类。
UNTextInputNotificationAction
创建文本回复框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| // 在桌面对本地通知进行回复 - (void)replyLocalNotificationAtDesktopWithInputIdentifier:(NSString *)inputIdentifier inputTitle:(NSString *)inputTitle inputBtnTitle:(NSString *)inputBtnTitle inputPlaceholder:(NSString *)inputPlaceholder categoryIdentifier:(NSString *)categoryIdentifier title:(NSString *)title body:(NSString *)body time:(int)time repeats:(BOOL)repeats inentifier:(NSString *)identifier { // 创建管理类 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 创建回复框 UNTextInputNotificationAction * inputAction = [UNTextInputNotificationAction actionWithIdentifier:inputIdentifier title:inputIdentifier options:UNNotificationActionOptionAuthenticationRequired textInputButtonTitle:inputBtnTitle textInputPlaceholder:inputPlaceholder]; // 创建通知模板 UNNotificationCategory * category = [UNNotificationCategory categoryWithIdentifier:categoryIdentifier actions:@[inputAction] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction]; // 设置通知内容 UNMutableNotificationContent * content = [[UNMutableNotificationContent alloc] init]; // 设置通知请求发送时App图标上显示的数字 // content.badge = @1; // 设置通知的标题 content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; // 设置通知的副标题 // content.subtitle = @""; // 设置通知的主体 content.body = [NSString localizedUserNotificationStringForKey:body arguments:nil]; // 设置通知的提示音 content.sound = [UNNotificationSound defaultSound]; // 设置从通知激活App时的launchImage图片 // content.launchImageName = @""; // 设置通知模板(categoryIdentifier和上面的保持一致) content.categoryIdentifier = categoryIdentifier; [center setNotificationCategories:[NSSet setWithObjects:category, nil]]; /* 设置触发器: 计时器触发 1.TimeInterval:时间间隔 2.repeats:是否重复*/ UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:repeats]; /* 设置通知请求 1.Identifier:通知标识 2.content:通知内容 3.trigger:触发器 */ UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; // 添加通知请求 [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"添加推送通知失败"); }else { NSLog(@"添加推送通知成功"); } }]; }
|
- UNNotificationAction创建用户交互按钮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| // 在桌面对本地通知进行按钮交互 // 在桌面对本地通知进行按钮交互 - (void)supportLocationNotificationUserInterfaceButton{
// 创建通知管理类 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; /* 创建交互按钮(系统模板最多支持添加4个交互按钮) UNNotificationActionOptionNone: 无设置 */ UNNotificationAction * action1 = [UNNotificationAction actionWithIdentifier:@"action" title:@"用户交互按钮1" options:UNNotificationActionOptionNone]; UNNotificationAction * action2 = [UNNotificationAction actionWithIdentifier:@"action" title:@"用户交互按钮2" options:UNNotificationActionOptionNone]; UNNotificationAction * action3 = [UNNotificationAction actionWithIdentifier:@"action" title:@"用户交互按钮3" options:UNNotificationActionOptionNone]; UNNotificationAction * action4 = [UNNotificationAction actionWithIdentifier:@"action" title:@"用户交互按钮4" options:UNNotificationActionOptionNone];
// 创建通知模板 UNNotificationCategory * category = [UNNotificationCategory categoryWithIdentifier:@"myNotificationCategoryButton" actions:@[action1,action2,action3,action4] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
// 通知内容 UNMutableNotificationContent * content = [[UNMutableNotificationContent alloc] init]; // 设置通知请求发送时App图标上显示的数字 // content.badge = @1; // 设置通知的标题 content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; // 设置通知的副标题 // content.subtitle = @""; // 设置通知的主体 content.body = [NSString localizedUserNotificationStringForKey:body arguments:nil]; // 设置通知的提示音 content.sound = [UNNotificationSound defaultSound]; // 设置从通知激活App时的launchImage图片 // content.launchImageName = @""; // 设置通知模板(categoryIdentifier和上面的保持一致) content.categoryIdentifier = categoryIdentifier; [center setNotificationCategories:[NSSet setWithObjects:category, nil]]; /* 设置触发器: 计时器触发 1.TimeInterval:时间间隔 2.repeats:是否重复*/ UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:repeats]; /* 设置通知请求 1.Identifier:通知标识 2.content:通知内容 3.trigger:触发器 */ UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; // 添加通知请求 [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"添加推送通知失败"); }else { NSLog(@"添加推送通知成功"); } }]; }
|
- 通知扩展
通过 UserNotification
框架,开发者已经可以完成从前很难实现的效果。然后这都不是这个框架最强大的地方,它的最强大的功能是通过扩展实现 完全自定义的通过UI界面
。也即 Notification Content Extension
。在项目新建一个 Target
后,然后选择 Notification Content Extension
扩展文件并创建,此时这个扩展文件自带了一个故事板 storyBoard
和一个 NotificationViewCenter
类,开发者可以在 storyBoard
中或者 NotificationViewCenter
中直接定制需要的UI界面即可,具体方法可以去看API。需要注意的是,NotificationViewCenter
类自动遵守了 UNNotificationContentExtension
协议,这个协议专门用来处理自定义的通知UI的内容展示。
注意:
在自定义的的通知界面上,虽然可以放置按钮或者任何UI控件,但其不能进行用户交互,唯一可以进行交互的方式是通过协议中的媒体按钮及其回调方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| // 当用户点击通知中的用户交互按钮时会调用,开发者可以从notification对象中拿到附件等内容进行UI刷新 - (void)didReceiveNotification:(UNNotification *)notification; - (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption option))completion;
// 返回媒体按钮位置 @property (nonatomic, readonly, assign) CGRect mediaPlayPauseButtonFrame;
// 返回媒体按钮颜色 @property (nonatomic, readonly, copy) UIColor *mediaPlayPauseButtonTintColor;
// 点击播放和暂停播放按钮的回调 - (void)mediaPlay; - (void)mediaPause;
// 打开和关闭通知的回调 - (void)performNotificationDefaultAction; - (void)dismissNotificationContentExtension
// 媒体开始播放和暂停的回调 - (void)mediaPlayingStarted; - (void)mediaPlayingPaused .
|
在这个 NSExtensionAttributes 字典下,我们有三个属性可以添加
(1)UNNotificationExtensionCategory(必须要有,系统已经创建好)
解释:对应这个key的值,可以是字符串,也可以是一个数组,每一个字符串都是一个identifier,这个identifier对应着每一个 UNMutableNotificationContent
的 categoryIdentifier
的属性。
简单来说,就是在收到通知的时候,我们可以让服务器把这个通知的 categoryIdentifier
带上,作用是,我们可以根据视频、音乐、图片,来分别自定义我们的通知内容。不同的分类标识符,也会在我们讲到 UNNotificationAction
的时候,帮助我们区分是什么类型的通知,方便我们对不同类型的通知做出不同的操作行为。上面的截图中,我是一个字符串的形式。下图为数组形式:
这里设置categoryIdentifier,最好让服务器的推送内容带上这个,然后我们好更加的定制化。不建议本地写死。
(2)UNNotificationExtensionInitialContentSizeRatio(必须要有,系统已经创建好)
解释:这个值的类型是一个浮点类型,代表的是 高度与宽度的比值
。系统会使用这个比值,作为初始化view的大小。举个简单的例子来说,如果该值为 1
,则该视图为 正方形
。如果为 0.5
,则代表 高度是宽度的一半
。
注意:这个值只是初始化的一个值,在这个扩展添加后,可以重写frame,展示的时候,在我们还没打开这个视图预览时,背景是个类似图片占位的灰色,那个灰色的高度宽度之比,就是通过这个值来设定。
(3)UNNotificationExtensionDefaultContentHidden(可选)
解释:这个值是一个BOOL值,当为YES时,会隐藏上方原本推送的内容视图,只会显示我们自定义的视图。(因为在自定义视图的时候,我们可以取得推送内容,然后按照我们想要的布局,展示出来)如果为NO时(默认为NO),推送视图就会既有我们的自定义视图,也会有系统原本的推送内容视图(这里附件是不会显示的,只会显示body里面的文字哟)
(4)至于 NSExtensionMainStoryboard
以及 NSExtensionPointIdentifier
,系统默认生成,大家直接用就好,如果需要更改的,只能更改使用的 storyboard
的名字(不过应该没人会把系统的删除在建立一个吧
MainInterface.storyboard:
这个就是个简单的storyboard文件,内部有一个View,这个View就是在上面的图层中的自定义View视图了。它与NotificationViewController所绑定。
NotificationViewController:
这是是系统帮我们默认创建了一个控制器,继承UIViewController,其实就是一个控制器啦。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| // NotificationViewController.m
// MyNotificationContentExtension
#import "NotificationViewController.h"
#import <UserNotifications/UserNotifications.h>
#import <UserNotificationsUI/UserNotificationsUI.h>
@interface NotificationViewController () <UNNotificationContentExtension>
@property (nonatomic, strong) UILabel *customTitleLabel1;
@property (nonatomic, strong) UILabel *customTitleLabel2;
@property (nonatomic, strong) UIImageView *customImageView1;
@property (nonatomic, strong) UIImageView *customImageView2;
@end
@implementation NotificationViewController
- (void)viewDidLoad {
[super viewDidLoad];
//屏幕宽
CGFloat screen_width = [UIScreen mainScreen].bounds.size.width;
self.view.backgroundColor = [UIColor redColor];
//自定义Label
self.customTitleLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(, , screen_width, )];
self.customTitleLabel1.textColor = [UIColor whiteColor];
self.customTitleLabel1.textAlignment = NSTextAlignmentCenter;
self.customTitleLabel1.backgroundColor = [UIColor greenColor];
//自定义UIImageView
self.customImageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(, , screen_width/, )];
self.customImageView2 = [[UIImageView alloc] initWithFrame:CGRectMake(screen_width/, , screen_width/, )];
self.customImageView1.backgroundColor = [UIColor purpleColor];
self.customImageView2.backgroundColor = [UIColor blueColor];
//自定义Label
self.customTitleLabel2 = [[UILabel alloc] initWithFrame:CGRectMake(, CGRectGetMaxY(self.customImageView1.frame)+, screen_width, )];
self.customTitleLabel2.textColor = [UIColor whiteColor];
self.customTitleLabel2.textAlignment = NSTextAlignmentCenter;
self.customTitleLabel2.backgroundColor = [UIColor orangeColor];
//添加控件
[self.view addSubview:self.customTitleLabel1];
[self.view addSubview:self.customTitleLabel2];
[self.view addSubview:self.customImageView1];
[self.view addSubview:self.customImageView2];
}
/* 收到通知时触发,但是这个是退出进程之后才使用,只适用于远程推送(所以本地推送,这两个方法是不会执行的) 拿到推送通知内容,刷新自定义的UI */ - (void)didReceiveNotification:(UNNotification *)notification { NSLog(@"notification---------%@",notification);
}
// 用户交互时触发 - (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption option))completion { NSLog(@"response----------%@",response); }
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| // 支持完全自定义UI的通知 - (void)supportCustomUILocationNotification {
// 创建交互按钮 UNNotificationAction * action = [UNNotificationAction actionWithIdentifier:@"action" title:@"自定义的Action" options:UNNotificationActionOptionNone];
// 创建通知模板 // "myNotificationCategory" 要与 plist 中配置的保持一样 UNNotificationCategory * category = [UNNotificationCategory categoryWithIdentifier:@"myNotificationCategory" actions:@[action] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
// 通知内容类 UNMutableNotificationContent * content = [UNMutableNotificationContent new]; // 设置通知请求发送时APP图标上显示的数字 content.badge = @1; // 设置通知的内容 content.body = @"iOS10新通知内容,普通通知,欢迎哥来了"; // 设置通知提示音 content.sound = [UNNotificationSound defaultSound]; // 设置通知的副标题 content.subtitle = @"这是通知副标题"; // 设置通知的标题 content.title = @"这是通知标题"; // 设置从通知激活App时的lanunchImage图片 content.launchImageName = @"lun";
// 设置通知模板 // categoryIdentifier要与上面创建category的标识保持一致 content.categoryIdentifier = @"myNotificationCategory"; [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObjects:category, nil]];
// 设置触发器 // 计时器触发器 UNTimeIntervalNotificationTrigger * timrTrigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval: repeats:NO];
// 设置通知请求 UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:@"UNNotificationCustomUIH" content:content trigger:timrTrigger];
// 添加通知请求 [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (!error) { NSLog(@""); } }]; }
|
- 重写媒体按钮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #pragma mark - 重写媒体按钮 // 重写媒体按钮的frame - (CGRect)mediaPlayPauseButtonFrame { return CGRectMake(, , , ); }
// 重写媒体按钮的颜色 - (UIColor *)mediaPlayPauseButtonTintColor { return [UIColor yellowColor]; }
// 重写媒体按钮类型 - (UNNotificationContentExtensionMediaPlayPauseButtonType)mediaPlayPauseButtonType { return UNNotificationContentExtensionMediaPlayPauseButtonTypeDefault; }
// 接收媒体按钮播放事件 - (void)mediaPlay { NSLog(@"mediaPlay---------------开始播放"); }
// 接收媒体按钮暂停事件 - (void)mediaPause { NSLog(@"mediaPause---------------暂停播放"); }
|
- 通知的代理方法
UserNotification框架对于通知的回调处理,是通过UNNotificationCenterDelegate协议来实现的。代理方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #pragma mark - UNUserNotificationCenterDelegate /* App在前台时,才会调用此方法: 如果未实现该方法或未及时调用该处理程序,则不会显示该通知。 应用程序可以选择将通知显示为声音,徽章,警报和/或显示在通知列表中。 该决定应基于通知中的信息是否对用户可见。 */ -(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{ NSLog(@"App在前台,收到了通知"); // 处理通知 UNNotificationContent * content = notification.request.content; if (content) { NSLog(@"title:%@ body:%@",content.title,content.body); } /* 处理完成后,调用 completionHandler,用于指示在前台显示通知的形式 UNNotificationPresentationOptionNone:不在前台显示 UNNotificationPresentationOptionAlert:在前台显示 ... */ completionHandler(UNNotificationPresentationOptionNone); }
/* 当接收到通知后,在用户点击通知激活应用程序时调用这个方法,无论是在前台还是后台 */ - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler { NSLog(@"App无论是在前台还是后台,收到了通知,用户点击该通知"); // 如果有内容 UNNotificationContent * content = response.notification.request.content; if (content) { NSLog(@"title:%@ body:%@",content.title,content.body); } }
|
总结
- 将上述代码封装到一个管理类 LocalNofiManager 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
| / // LocalNotificationManager.m // JiAnBaoStandard // // Created by Mac on 2023/8/10. // Copyright © 2023 JITPlatform. All rights reserved. //
#import "LocalNotiManager.h"
@interface LocalNotiManager ()<UNUserNotificationCenterDelegate> @end @implementation LocalNotiManager // 单例 + (instancetype)sharedManager{ static LocalNotiManager * manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [[self alloc] init]; }); return manager; }
#pragma mark - 本地通知授权 - (void)localNotificationAuthorization{ if (@available(iOS 10.0, *)) { [self localNotificationAuthorizationIOS10AndAbove]; }else{ [self localNotificationAuthorizationIOS10AndBelow]; } }
#pragma mark - 推送本地通知 - (void)pushLocalNotificationWithTime:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ if (@available(iOS 10.0, *)) { [self pushLocalNotificationIOS10AndAboveWithTime:time title:title body:body repeats:repeats identifier:identifier]; }else{ [self pushLocalNotificationIOS10AndBelowWithTime:time title:title body:body repeats:repeats identifier:identifier]; } }
#pragma mark - iOS 10.0 及以上 // 本地通知授权 - (void)localNotificationAuthorizationIOS10AndAbove{ // 使用 UNUserNotificationCenter 来管理通知 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 设置通知中心的代理 center.delegate = self; // iOS 10.0使用以下方法注册,才能得到授权 [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionBadge + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) { // 用户是否同意 if (granted) { NSLog(@"用户同意授权"); }else { NSLog(@"用户不同意授权"); } }]; }
// 推送本地通知 iOS 10.0 及以上(普通) - (void)pushLocalNotificationIOS10AndAboveWithTime:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionBadge + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (!granted) { dispatch_async(dispatch_get_main_queue(), ^{ [SVPManager showWithStatus:@"请您在前往 设置->通用->零信任->通知->开启允许通知 权限,以便为您提供本地通知服务" time:2.5]; }); return; }; }]; // 1.创建通知管理类 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; // 2.设置通知内容 UNMutableNotificationContent * content = [[UNMutableNotificationContent alloc] init]; // 设置通知请求发送时App图标上显示的数字 // content.badge = @1; // 设置通知的标题 content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; // 设置通知的副标题 // content.subtitle = @""; // 设置通知的主体 content.body = [NSString localizedUserNotificationStringForKey:body arguments:nil]; // 设置通知的提示音 content.sound = [UNNotificationSound defaultSound]; // 设置从通知激活App时的launchImage图片 // content.launchImageName = @""; /* 3.设置触发器: 计时器触发 1.TimeInterval:时间间隔 2.repeats:是否重复*/ UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:repeats]; /* 设置触发器: 周期日历触发 */ // NSDateComponents * components = [[NSDateComponents alloc] init]; // components.year = 2023; // components.month = 11; // components.day = 2; // UNCalendarNotificationTrigger * trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:repeats]; /* 设置触发器:地域触发 */ // CLRegion * region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(33.0, 11.0) radius:100 identifier:@"region"]; // UNLocationNotificationTrigger * trigger = [UNLocationNotificationTrigger triggerWithRegion:region repeats:repeats]; /* 4.设置通知请求 1.Identifier:通知标识 2.content:通知内容 3.trigger:触发器 */ UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; // 5.添加通知请求 [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"添加推送通知请求失败"); }else { NSLog(@"添加推送通知请求成功"); } }]; }
#pragma mark - UNUserNotificationCenterDelegate /* App在前台时,才会调用此方法: 1.如果未实现该方法或未及时调用该处理程序,则不会显示该通知。 2.应用程序可以选择将通知显示为声音,徽章,警报和/或显示在通知列表中。 3.该决定应基于通知中的信息是否对用户可见。 */ -(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{ NSLog(@"App在前台,收到了通知"); // 处理通知 UNNotificationContent * content = notification.request.content; if (content) { NSLog(@"title:%@ body:%@",content.title,content.body); } /* 处理完成后,调用 completionHandler,用于指示在前台显示通知的形式 UNNotificationPresentationOptionNone:不在前台显示 UNNotificationPresentationOptionAlert:在前台显示 ... */ completionHandler(UNNotificationPresentationOptionNone); } /* 当接收到通知后,在用户点击通知激活App时调用这个方法(无论是在前台还是后台) */ - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{ NSLog(@"App无论是在前台还是后台,收到了通知,用户点击该通知"); // 如果有内容 UNNotificationContent * content = response.notification.request.content; if (content) { NSLog(@"title:%@ body:%@",content.title,content.body); } }
#pragma mark - iOS 10.0 及以下 // 本地通知授权 - (void)localNotificationAuthorizationIOS10AndBelow{ // 如果没有授权,则申请授权 if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) { // 开始授权 UIUserNotificationSettings * notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings]; } }
// 推送本地通知 iOS 10.0 及以下 - (void)pushLocalNotificationIOS10AndBelowWithTime:(int)time title:(NSString *)title body:(NSString *)body repeats:(BOOL)repeats identifier:(NSString *)identifier{ if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) { [SVPManager showWithStatus:@"请您在前往 设置->通用->零信任->通知->开启允许通知 权限,以便为您提供本地通知服务" time:2]; return; } // 1.创建通知对象 UILocalNotification * notification = [[UILocalNotification alloc] init]; // 2.设置触发通知的时间(几秒后发送) NSDate * fireDate = [NSDate dateWithTimeIntervalSinceNow:time]; notification.fireDate = fireDate; // 3.设置通知属性 // 通知标题 notification.alertTitle = title; // 通知主体 notification.alertBody = body; // 待机界面开启左滑按钮 notification.hasAction = YES; // 待机界面的滑动按钮提示 notification.alertAction = @"点击查看消息"; // 在收到通知时播放的声音,默认消息声音 notification.soundName = UILocalNotificationDefaultSoundName; // 设置启动屏 // notification.alertLaunchImage = @""; // 传递的用户数据 // notification.userInfo = @{}; // 图标的消息数 // notification.applicationIconBadgeNumber = 1; // 时区 // notification.timeZone = [NSTimeZone defaultTimeZone]; // 设置重复的间隔 // notification.repeatInterval = kCFCalendarUnitSecond; // 附加操作 // notification.category = @"choose"; // 4.执行本地通知 [[UIApplication sharedApplication] scheduleLocalNotification:notification]; }
/* App处于kill掉时,点击通知栏进入App,使用该方法接收本地(远程)通知 */ - (void)receiveLocalNotificationWithLaunchOptions:(NSDictionary *)launchOptions{ /* App被kill掉,通过通知启动App 1.本地的 key - UIApplicationLaunchOptionsLocalNotificationKey 2.远程的 key - UIApplicationLaunchOptionsRemoteNotificationKey */ if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) { UILocalNotification * notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; [self handleLocalNotificationWithWithNotification:notification userInfo:launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]]; } } // 处理本地通知 - (void)handleLocalNotificationWithWithNotification:(UILocalNotification *)notification userInfo:(NSDictionary *)userInfo{ NSLog(@"title:%@ body:%@",notification.alertTitle,notification.alertBody); }
@end
|
- AppDelegate 中实现
1 2 3 4
| // 本地通知授权 [[LocalNotiManager sharedManager] localNotificationAuthorization]; // 接收本地通知 [[LocalNotiManager sharedManager] receiveLocalNotificationWithLaunchOptions:launchOptions];
|
- AppDelegate 中回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #pragma mark - 接收本地通知 /* App处于挂起或运行时,调用该方法接收本地(远程)通知 1.当App在前台状态下,点击推送通知,会调用该方法 2.当App在后台状态下,点击推送通知,会调用该方法(从锁屏界面点击推送通知也会执行) */ - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{ NSLog(@"%@",notification); // 前台点击通知消息 if (application.applicationState == UIApplicationStateActive) { NSLog(@"处理前台接受通知的业务"); } // 后台点击通知消息 else { NSLog(@"处理后台台接受通知的业务"); [[LocalNotiManager sharedManager] handleLocalNotificationWithWithNotification:notification userInfo:notification.userInfo]; } } // 当用户点击允许或者不允许时,会执行如下代理方法,我们在其中实现处理逻辑 - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{ NSLog(@"当用户点击允许或者不允许时,会执行如下代理方法"); }
|