七、定义通知模板UNNotificationCategory
聊天类软件在iOS系统中,常常采用后台推送的方式推送新消息,用户可以在不进入应用程序的情况下,直接在左面回复通知推送过来的信息,这种功能就是通过UNNotificationCategory模板与UNNotificationAction用户活动来实现的。关于文本回复框,UserNotification框架中提供了UNTextInputNotificationAction类,其是UNNotificationAction的子类。示例代码如下:
//创建用户活动
/*
options参数可选如下:
//需要在解开锁屏下使用
UNNotificationActionOptionAuthenticationRequired
//是否指示有破坏性
UNNotificationActionOptionDestructive
//是否允许活动在后台启动app
UNNotificationActionOptionForeground
//无设置
UNNotificationActionOptionNone
*/
UNTextInputNotificationAction * action = [UNTextInputNotificationAction actionWithIdentifier:@"action" title:@"回复" options:UNNotificationActionOptionAuthenticationRequired textInputButtonTitle:@"活动" textInputPlaceholder:@"请输入回复内容"];
//创建通知模板
UNNotificationCategory * category = [UNNotificationCategory categoryWithIdentifier:@"myNotificationCategoryText" actions:@[action] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
UNMutableNotificationContent * content = [UNMutableNotificationContent new];
content.badge = @1;
content.body = @"这是iOS10的新通知内容:普通的iOS通知";
//默认的通知提示音
content.sound = [UNNotificationSound defaultSound];
content.subtitle = @"这里是副标题";
content.title = @"这里是通知的标题";
//设置通知内容对应的模板 需要注意 这里的值要与对应模板id一致
content.categoryIdentifier = @"myNotificationCategoryText";
//设置5S之后执行
UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObjects:category, nil]];
UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:@"NotificationDefaultText" content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
}];
需要注意,要使用模板,通知内容UNNotificationContent的categoryIdentifier要与UNNotificationCategory的id一致。效果如下:
也可以为通知模板添加多个自定义的用户交互按钮,示例如下:
UNNotificationAction * action = [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:@"myNotificationCategoryBtn" actions:@[action,action2,action3,action4] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
UNMutableNotificationContent * content = [UNMutableNotificationContent new];
content.badge = @1;
content.body = @"这是iOS10的新通知内容:普通的iOS通知";
//默认的通知提示音
content.sound = [UNNotificationSound defaultSound];
content.subtitle = @"这里是副标题";
content.title = @"这里是通知的标题";
content.categoryIdentifier = @"myNotificationCategoryBtn";
//设置5S之后执行
UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];
UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:@"NotificationDefault" content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObjects:category, nil]];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
}];
需要注意,系统模板最多支持添加4个用户交互按钮,如下图:
八、自定义通知模板UI
通过前边的介绍,我们发现通过UserNotification框架开发者已经可以完成许多从来很难实现的效果。然而这都不是UserNotification框架最强大的地方,UserNotification框架最强大的地方在于其可以完全自定义通知的UI界面。
完全自定义通知界面是通过iOS扩展来实现的,首先创建一个新的target,如下图:
选择Notification Content,如下:
创建完成后,会发现工程中多了一个Notification Content的扩展,其中自带一个storyboard文件和一个NotificationViewController类,开发者可以在storyboard文件或者直接在Controller类中进行自定义界面的编写。
需要注意,NotificationViewController自动遵守了UNNotificationContentExtension协议,这个协议专门用来处理自定义通知UI的内容展示,其中方法列举如下:
//接收到通知时会被调用
/*
开发者可以从notification对象中拿到附件等内容进行UI刷新
*/
- (void)didReceiveNotification:(UNNotification *)notification;
//当用户点击了通知中的用户交互按钮时会被调用
/*
response对象中有通知内容相关信息
在回调block块completion中,开发者可以传入一个UNNotificationContentExtensionResponseOption参数来告诉系统如何处理这次用户活动
UNNotificationContentExtensionResponseOption枚举中可选值如下:
typedef NS_ENUM(NSUInteger, UNNotificationContentExtensionResponseOption) {
//不关闭当前通知界面
UNNotificationContentExtensionResponseOptionDoNotDismiss,
//关闭当前通知界面
UNNotificationContentExtensionResponseOptionDismiss,
//关闭当前通知界面并将用户活动传递给宿主app处理
UNNotificationContentExtensionResponseOptionDismissAndForwardAction,
} __IOS_AVAILABLE(10_0) __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE __OSX_UNAVAILABLE;
*/
- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption option))completion;
/*
这个属性作为get方法进行实现 这个方法用来返回一个通知界面要显示的媒体按钮
typedef NS_ENUM(NSUInteger, UNNotificationContentExtensionMediaPlayPauseButtonType) {
//不显示媒体按钮
UNNotificationContentExtensionMediaPlayPauseButtonTypeNone,
//默认的媒体按钮 当点击按钮后 进行播放与暂停的切换 按钮始终显示
UNNotificationContentExtensionMediaPlayPauseButtonTypeDefault,
//Overlay风格 当点击按钮后,媒体播放,按钮隐藏 点击媒体后,播放暂停,按钮显示。
UNNotificationContentExtensionMediaPlayPauseButtonTypeOverlay,
} __IOS_AVAILABLE(10_0) __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE __OSX_UNAVAILABLE;
*/
@property (nonatomic, readonly, assign) UNNotificationContentExtensionMediaPlayPauseButtonType mediaPlayPauseButtonType;
//返回媒体按钮的位置
@property (nonatomic, readonly, assign) CGRect mediaPlayPauseButtonFrame;
//返回媒体按钮的颜色
@property (nonatomic, readonly, copy) UIColor *mediaPlayPauseButtonTintColor;
//点击播放按钮的回调
- (void)mediaPlay;
//点击暂停按钮的回调
- (void)mediaPause;
//媒体开始播放的回调
- (void)mediaPlayingStarted __IOS_AVAILABLE(10_0) __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE __OSX_UNAVAILABLE;
//媒体开始暂停的回调
- (void)mediaPlayingPaused __IOS_AVAILABLE(10_0) __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE __OSX_UNAVAILABLE;
需要注意,自定义的通知界面上虽然可以放按钮,可以放任何UI控件,但是其不能进行用户交互,唯一可以进行用户交互的方式是通过协议中的媒体按钮及其回调方法。
定义好了通知UI模板,若要进行使用,还需要再Notification Content扩展中的info.plist文件的NSExtension字典的NSExtensionAttributes字典里进行一些配置,正常情况下,开发者需要进行配置的键有3个,分别如下:
UNNotificationExtensionCategory:设置模板的categoryId,用于与UNNotificationContent对应。
UNNotificationExtensionInitialContentSizeRatio:设置自定义通知界面的高度与宽度的比,宽度为固定宽度,在不同设备上有差别,开发者需要根据宽度计算出高度进行设置,系统根据这个比值来计算通知界面的高度。
UNNotificationExtensionDefaultContentHidden:是有隐藏系统默认的通知界面。
配置info.plist文件如下:
用如下的代码创建通知:
UNNotificationAction * action = [UNNotificationAction actionWithIdentifier:@"action" title:@"活动标题1" options:UNNotificationActionOptionNone];
//根据id拿到自定义UI的模板
UNNotificationCategory * category = [UNNotificationCategory categoryWithIdentifier:@"myNotificationCategoryH" actions:@[action] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
UNMutableNotificationContent * content = [UNMutableNotificationContent new];
content.badge = @1;
content.body = @"这是iOS10的新通知内容:普通的iOS通知";
//默认的通知提示音
content.sound = [UNNotificationSound defaultSound];
content.subtitle = @"这里是副标题";
content.title = @"这里是通知的标题";
content.categoryIdentifier = @"myNotificationCategoryH";
//设置5S之后执行
UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];
UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:@"NotificationDefaultCustomUIH" content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObjects:category, nil]];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
}];
效果如下图:
如果将UNNotificationExtensionDefaultContentHidden键值设置为0或者不设置,则不会隐藏系统默认的UI,如下: