iOS 10 的推送 User Notifications Framework

介绍

User Notifications Framework 是苹果在 WWDC 2016 推出的。iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifications.framework 来集中管理和使用 iOS 系统中通知的功能。在此基础上,Apple 还增加了撤回单条通知,更新已展示通知,中途修改通知内容,在通知中展示图片视频,自定义通知 UI 等一系列新功能,非常强大。

iOS 10 以前的推送

iOS 10 以前推送分为 Local Notifications(本地推送) 和 Remote Notifications(远程推送)。

本地推送:通过 App 本地定制,加入到系统的 Schedule 里,然后在指定的时间推送指定文字。


远程推送:通过服务端向苹果推送服务器 Apple Push Notification Service (APNs) 发送 Notification Payload,之后 APNs 再将推送下发到指定设备的 指定 App 上。


User Notifications Framework

基本配置

如果只是简单的本地推送,跳过 1 、2 步骤,直接到步骤 3。

1、 如果你的 App 有远端推送的话,那你需要开发者账号的,需要新建一个对应你 bundle 的 push 证书。 具体的证书制作请参考这里

2、 Capabilities 中打开 Push Notifications 开关在 XCode7 中这里的开关不打开,推送也是可以正常使用的,但是在 XCode8 中,这里的开关必须要打开,不然会报错:

Error Domain=NSCocoaErrorDomain Code=3000 "未找到应用程序的“aps-environment”的授权字符串" UserInfo={NSLocalizedDescription=未找到应用程序的“aps-environment”的授权字符串}


权限申请

在使用 UserNotifications 框架的 API 的时候,首先要导入 UserNotifications 框架:

#import <UserNotifications/UserNotifications.h>

注册推送

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {

    if (!error)

        {

            NSLog(@"请求授权成功");

        }

        else

        {

            NSLog(@"请求授权失败");

        }

}];

Notification settings:之前注册推送服务,用户点击了同意还是不同意,以及用户之后又做了怎样的更改我们都无从得知,现在 apple 开放了这个 API,我们可以直接获取到用户的设定信息了。注意 UNNotificationSettings 是只读对象哦,不能直接修改!只能通过以下方式获取

[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {

    NSLog(@"%@", settings);

}];

打印

<UNNotificationSettings: 0x6000022f9dc0; 

authorizationStatus: NotDetermined, 

notificationCenterSetting: NotSupported, 

soundSetting: NotSupported, 

badgeSetting: NotSupported, 

lockScreenSetting: NotSupported, 

carPlaySetting: NotSupported, 

criticalAlertSetting: NotSupported, 

alertSetting: NotSupported, 

alertStyle: None, 

providesAppNotificationSettings: No>

Token Registration

[[UIApplication sharedApplication] registerForRemoteNotifications];

获取设备的Device Token

//获取DeviceToken成功

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

{

    NSString *deviceString = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];

    deviceString = [deviceString stringByReplacingOccurrencesOfString:@" " withString:@""];

    NSLog(@"deviceToken:%@",deviceString);

}


//获取DeviceToken失败

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error

{

    NSLog(@"[DeviceToken Error]:%@\n",error.description);

}

接收推送的代理方法

// App处于前台接收通知时

// 只有app处于前台状态下才会调用,后台状态或者应用杀死下是不会调用这个方法的

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler 


// App通知的点击事件

// 用户点击消息才会触发

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler 

苹果把本地通知跟远程通知合二为一。区分本地通知跟远程通知的类是UNPushNotificationTrigger.h 类中,UNPushNotificationTrigger 的类型是新增加的。

UNPushNotificationTrigger (远程通知) 远程推送的通知类型

UNTimeIntervalNotificationTrigger (本地通知) 一定时间之后,重复或者不重复推送通知。我们可以设置timeInterval(时间间隔)和repeats(是否重复)。

UNCalendarNotificationTrigger(本地通知) 一定日期之后,重复或者不重复推送通知 例如,你每天8点推送一个通知,只要dateComponents为8,如果你想每天8点都推送这个通知,只要repeats为YES就可以了。

UNLocationNotificationTrigger (本地通知)地理位置的一种通知,

当用户进入或离开一个地理区域来通知。

内容

以前只能展示一条文字,现在可以有 title 、subtitle 以及 body 了。


定制方法如下:

//本地通知

UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];

content.title = @"CALENDAR";

content.subtitle = @"Lunch";

content.body = @"Today at 12:00 PM";

content.badge = @1;


//远程推送

{

"aps" : {

    "alert" : { 

         "title" : "CALENDAR", 

         "subtitle" : "Lunch",         

         "body" : "Today at 12:00 PM"

                },

    "badge" : 1

        },

}

Triggers

UNTimeIntervalNotificationTrigger 定时推送

UNCalendarNotificationTrigger 定期推送

UNLocationNotificationTrigger 定点推送

//60 秒后提醒

//timeInterval:单位为秒(s)  repeats:是否循环提醒

UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:60 repeats:NO];


// 在每周一早上 8:00 提醒

NSDateComponents *components = [[NSDateComponents alloc] init];

components.weekday = 2;

components.hour = 8;

UNCalendarNotificationTrigger *trigger3 = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];


//首先得导入#import <CoreLocation/CoreLocation.h>,不然会regin创建有问题。

CLLocationCoordinate2D center1 = CLLocationCoordinate2DMake(31.234567, 117.4567890);

  CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center1 radius:500 identifier:@"桂林路"];

UNLocationNotificationTrigger *trigger4 = [UNLocationNotificationTrigger triggerWithRegion:region repeats:NO];

Add Request

NSString *requestIdentifier = @"sampleRequest";

UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier

                                                                          content:content

                                                                          trigger:trigger1];

[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {


}];

推送小结

整个推送的过程如下


Local Notifications 通过定义 Content 和 Trigger 向 UNUserNotificationCenter 进行 request 这三部曲来实现。

Remote Notifications 则向 APNs 发送 Notification Payload 。

Notification Handling

设定了推送,然后就结束了?iOS 10 并没有这么简单!

通过实现协议,使 App 处于前台时捕捉并处理即将触发的推送:

@interface AppDelegate () <UNUserNotificationCenterDelegate>


- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler

{

    completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);

}

让它只显示 alert 和 sound ,而忽略 badge 。

Notification Management

彻底掌控整个推送周期:

Local Notification 通过更新 request

Remote Notification 通过新的字段 apns-collapse-id

通过之前的 addNotificationRequest: 方法,在 id 不变的情况下重新添加,就可以刷新原有的推送。

NSString *requestIdentifier = @"sampleRequest";

UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier

                                                                      content:newContent

                                                                      trigger:newTrigger1];

[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {


}];

删除计划的推送:

[center removePendingNotificationRequestsWithIdentifiers:@[requestIdentifier]];

此外 UNUserNotificationCenter.h 中还有诸如删除所有推送、查看已经发出的推送、删除已经发出的推送等等强大的接口。

刷新原有的推送后,在通知中心的显示里,也会有相应的变化,这里注意第 2 条信息,现在比分是 1:0



比分刷新后为 1:1,在不产生新的推送条目的情况下位置被前置了!


上面简单介绍了 iOS 10 的新框架 User Notifications Framework,了解完 iOS 10 的框架之后,还要适配iOS 8 9 系统,是不是觉得很麻烦,笔者最近发现了一款 SDK ---- MobPush,兼容 iOS 8-12 系统,接入非常简单,3行代码就可以搞定推送。

MPushNotificationConfiguration *configuration = [[MPushNotificationConfiguration alloc] init];

configuration.types = MPushAuthorizationOptionsBadge | MPushAuthorizationOptionsSound | MPushAuthorizationOptionsAlert;

[MobPush setupNotification:configuration];

同时,MobPush 支持多样化推送场景、用户分群、AB 测试、智能推送等等功能,还有完善的数据统计后台可以从多个维度实时了解 APP 和用户的使用情况,了解更多

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容