介绍
这个demo可以帮助你快速的了解iOS10中引入的新通知功能,该功能向用户呈现了强大而灵活的通知。本文将会介绍如何给通知附加媒体内容、自定义通知UI等。
背景
iOS10为开发人员提供了更强大、更灵活的本地和远程通知,它引进了两个新的框架
- UserNotifications.framework
- UserNotificationsUI.framework
新的功能
- 通知支持视频、音频、图片
- App在前台仍然可以显示通知
- 给通知添加action操作
- 可以快速回复文本
- 支持gif图
- 自定义通知的界面
代码
我们基于iOS10的新的通知功能创建一个本地通知
在Xcode中,到工程设置Build Phases -> Link Binary With Libraries中添加UserNotifications.framework
和UserNotificationsUI.framework
引入头文件
import <UserNotifications/UserNotifications.h>
当应用处于前台时获取通知
首先需要遵守UNUserNotificationCenterDelegate
协议,实现userNotificationCenter:willPresentNotification:withCompletionHandler:
代理方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
{
completionHandler(UNNotificationPresentationOptionAlert);
}
注册通知服务
无论是远程通知还是本地通知都必须先注册通知服务,定义如下属性
@property(strong,nonatomic) UNUserNotificationCenter* notiCenter;
初始化这个属性
_notiCenter = [UNUserNotificationCenter currentNotificationCenter];
_notiCenter.delegate=self;
[_notiCenter requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
//Enable or disable features based on authorization.
if(granted)
{
[_notiCenter setDelegate:self];
[self generateTimerBasedNotification];
[self generateLocationBasedNotification];
// _categoryActionSet has collected all the actions from different kind of notifications and adding it to notification Center
[[self notiCenter] setNotificationCategories:_categoryActionSet];
}
}];
可以通过iOS10UNUserNotificationCenter
的API获取到通知设置的属性
// Read the notification setting, set by user
[_notiCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if(settings.soundSetting==UNNotificationSettingEnabled)
{
NSLog(@"Sound Notification is Enabled");
}
else
{
NSLog(@"Sound Notification is Disabled");
}
if(settings.alertSetting==UNNotificationSettingEnabled)
{
NSLog(@"Alert Notification is Enabled");
}
else
{
NSLog(@"Alert Notification is Disabled");
}
if(settings.badgeSetting==UNNotificationSettingEnabled)
{
NSLog(@"Badge is Enabled");
}
else
{
NSLog(@"Badge is Disabled");
}
}];
iOS10中新添加了两个扩展
- 通知服务(Notification Service)
- 通知内容(Notification Content)
Notification Service
它是运行在后台以用来下载远程通知中指定的URL,或者将远程通知的内容在展示给用户之前进行替换
在file->New->Target选择Notification Service Extension
添加完target后将会创建NotificationService.h
、NotificationService.m
、info.plist
三个文件
NotificationService
类派生自UNNotificationServiceExtension
,这个基类只有两个方法,而且通知服务仅用于远程通知
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *contentToDeliver))contentHandler;
此方法用于下载远程通知中的URL内容以展示给用户
- (void)serviceExtensionTimeWillExpire;
如果程序无法在给定的时间内(从设备接受到远程通知到传递给用户的时间)完成下载,那么此方法为备用方案,
一旦设备接受到远程通知并且将其展示给用户之前,系统将运行该服务扩展,首先,系统将会调用didReceiveNotificationRequest
,在这里可以从UNNotificationRequest
中获取到通知的数据,并获取到媒体的URL开始下载。如果再给定的时间下载失败或者下载没有完成,系统将会调用serviceExtensionTimeWillExpire
告诉我们分配给下载内容的时间将要过去,在这里可以有一些代替的解决方案,我们可以替换为本地的图片、视频、音频等。
Notification Content
在file->New->Target选择Notification Content
此内容扩展可以帮助我们添加自定义的视图,以及处理用户对通知的操作.
添加了target之后将会创建NotificationViewController.h
、NotificationViewController.m
、MainInterface.storyboard
和info.plist
。
使用MainInterface.storyboard
自定义我们的通知视图,在Notification View Controller Scene
拖拽我们想要的通知样式
当用户点击任何操作按钮时,系统都会调用didReceiveNotificationResponse
委托方法
带有媒体文件的通知
将图片添加到通知
使用UNMutableNotificationContent
类可以像通知中添加许多内容、
在本地通知中,我们可以将图片,音频或者视频的路径添加到UNMutableNotificationContent.attachments
UNMutableNotificationContent *notificationcontent = [[UNMutableNotificationContent alloc] init];
notificationcontent.title = [NSString localizedUserNotificationStringForKey:@"New Arrivals" arguments:nil];
notificationcontent.body = [NSString localizedUserNotificationStringForKey:@"New arrival of Your favourite products!"
arguments:nil];
notificationcontent.sound = [UNNotificationSound defaultSound];
// category identitifer should be unique and should match with identitifer of its corresponding UNNotificationCategory
notificationcontent.categoryIdentifier=@"com.mcoe.notificationcategory.timerbased";
NSError *error=nil;
// reading image from bundle and copying it to document directory.
NSURL *fileFromBundle =[[NSBundle mainBundle] URLForResource:@"psc" withExtension:@"png"];
// Destination URL
NSURL *url = [[self applicationDocumentsDirectory]URLByAppendingPathComponent:@"psc.png"];
NSError *error1;
// copying from bundle to document directory
[[NSFileManager defaultManager]copyItemAtURL:fileFromBundle toURL:url error:&error1];
// creating attachment with image url
UNNotificationAttachment *image_attachment=[UNNotificationAttachment attachmentWithIdentifier:@"com.mcoe.notificationcategory.timerbased" URL:url options:nil error:&error];
notificationcontent.attachments=[NSArray arrayWithObject:image_attachment];
notificationcontent.badge = @([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
向通知添加操作
主要有3种操作
- Default Actions - 默认操作是用户从通知打开应用
- Custom Actions - 可以直接从通知本身执行,无需启动应用
- Dismiss Actions - 关闭操作
// Adding custom actions
UNNotificationAction *checkoutAction = [UNNotificationAction actionWithIdentifier:@"com.mcoe.notificationcategory.timerbased.yes"
title:@"Check out"
options:UNNotificationActionOptionForeground];
UNNotificationAction *declineAction = [UNNotificationAction actionWithIdentifier:@"com.mcoe.notificationcategory.timerbased.no"
title:@"Decline"
options:UNNotificationActionOptionDestructive];
UNNotificationAction *laterAction = [UNNotificationAction actionWithIdentifier:@"com.mcoe.notificationcategory.timerbased.dismiss"
title:@"Later"
options:UNNotificationActionOptionDestructive];
NSArray *NotificationActions = @[ checkoutAction, declineAction, laterAction ];
// categoryWithIdentifier should match with the value of UNNotificationExtensionCategory in info.plist of its corresponding content extension
UNNotificationCategory *TimernotificationCategory=[UNNotificationCategory categoryWithIdentifier:@"com.mcoe.notificationcategory.timerbased" actions:NotificationActions intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
[_categoryActionSet addObject:TimernotificationCategory];
计划通知
本地通知可以通过三种方式触发
- 时间间隔
- 日历时间
- 位置信息
时间间隔
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger
triggerWithTimeInterval:3.f repeats:NO];
位置信息
//Creating region object and generating Notification trigger object out of it.
CLLocationCoordinate2D officeArea = CLLocationCoordinate2DMake(12.970540,80.251060);
CLCircularRegion* officeRegion = [[CLCircularRegion alloc] initWithCenter:officeArea
radius:10 identifier:@"My Office Bay"];
officeRegion.notifyOnEntry = YES;
officeRegion.notifyOnExit = YES;
UNLocationNotificationTrigger* locationTrigger = [UNLocationNotificationTrigger
triggerWithRegion:officeRegion repeats:YES];
创建请求对象并添加到通知中心
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"com.mcoe.notificationcategory.timerbased"
content:notificationcontent trigger:timerbasedtrigger];
[_notiCenter addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"added timer based NotificationRequest suceessfully!");
}
}];
注意
- 我们分配给
UNNotificationCategory
对象的category identifier
和通知内容扩展的info.plist
中的UNNotificationExtensionCategory
标示符名称应该相同 - 由于我们可以向项目中添加多个扩展,系统使用接受到的通知中的类别标示符名称找到其对应的扩展代码以调用其委托方法
-
UNNotificationExtensionInitialContentSizeRatio
在通知内容扩展的info.plist中指示自定义视图的宽高比,其范围在0到1之间。1标示自定义界面高度等于其宽度,0标示其高度是其宽度的一半