前言

在去年的苹果大会上,苹果带来的iOS 10 系统中将之前繁杂的推送通知统一成UserNotifications.framework 来集中管理和使用通知功能,还增加一些实用的功能——撤回单条通知、更新已展示通知、中途修改通知内容、在通知中显示多媒体资源、自定义UI等功能。
那么在ios10之前,ios的消息推送是怎么分类的呢?

ios 10之前

在ios之前,iOS推送分为Local Notifications(本地推送) 和 Remote Notifications(远程推送)。

本地推送

不需要服务器支持(无需联网)就能发出的推送通知,app本地创建通知,加入到系统的Schedule里,如果触发器条件达成时会推送相应的消息内容,如常见的定时任务闹钟等。

使用上也是非常简单。

/*@property(nonatomic,copy) NSDate *fireDate;@property(nonatomic,copy) NSTimeZone *timeZone; 时区@property(nonatomic) NSCalendarUnit repeatInterval; 重复间隔(枚举)@property(nonatomic,copy) NSCalendar *repeatCalendar; 重复日期(NSCalendar)@property(nonatomic,copy) CLRegion *region 设置区域(设置当进入某一个区域时,发出一个通知)@property(nonatomic,assign) BOOL regionTriggersOnce YES,只会在第一次进入某一个区域时发出通知.NO,每次进入该区域都会发通知@property(nonatomic,copy) NSString *alertBody;      @property(nonatomic) BOOL hasAction;                是否隐藏锁屏界面设置的alertAction@property(nonatomic,copy) NSString *alertAction;    设置锁屏界面一个文字@property(nonatomic,copy) NSString *alertLaunchImage;   启动图片@property(nonatomic,copy) NSString *alertTitle@property(nonatomic,copy) NSString *soundName;@property(nonatomic) NSInteger applicationIconBadgeNumber;@property(nonatomic,copy) NSDictionary *userInfo; // 设置通知的额外的数据*/- (IBAction)addLocalNote:(id)sender {// 创建一个本地通知UILocalNotification *localNote = [[UILocalNotification alloc] init];// 设置本地通知的一些属性(通知发出的时间/通知的内容)// 设置通知发出的时间localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];//设置通知的内容localNote.alertBody = @"吃饭了吗?";//设置锁屏界面的文字localNote.alertAction = @"查看具体的消息";//设置锁屏界面alertAction是否有效localNote.hasAction = YES;//设置通过点击通知打开APP的时候的启动图片(无论字符串设置成什么内容,都是显示应用程序的启动图片)localNote.alertLaunchImage = @"111";//设置通知中心通知的标题localNote.alertTitle = @"222222222222";//设置音效localNote.soundName = @"buyao.wav";//设置应用程序图标右上角的数字localNote.applicationIconBadgeNumber = 1;//设置通知之后的属性localNote.userInfo = @{@"name" : @"张三", @"toName" : @"李四"};//调度通知[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
}

当用户点击本地推送通知的时候,会自动打开app,这里有2种情况:app在后台运行,或者被系统进程杀死,对于这两种情况,我们怎么处理呢?

app后台运行


这时候我们只需要调用下AppDelegate方法即可。代码实现

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{// 跳转逻辑if (application.applicationState == UIApplicationStateActive) return;if (application.applicationState == UIApplicationStateInactive) {// 当应用在后台收到本地通知时执行的跳转代码[self jumpToSession];}NSLog(@"local notifacation %@", notification);
}- (void)jumpToSession
{UILabel *redView = [[UILabel alloc] init];redView.backgroundColor = [UIColor redColor];redView.frame = CGRectMake(0, 100, 300, 400);redView.numberOfLines = 0;// redView.text = [NSString stringWithFormat:@"%@", launchOptions];[self.window.rootViewController.view addSubview:redView];
}

app被杀死


对于app被杀死的情况,要先启动app,启动完毕会调用AppDelegate方法。
需要特别注意的是:在iOS8.0以后本地通知有了一些变化,如果要使用本地通知,需要得到用户的许可。
部分代码实现:

#define IS_iOS8 ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)@interface AppDelegate ()@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {/*UIUserNotificationTypeNone    = 0,      不发出通知UIUserNotificationTypeBadge   = 1 << 0, 改变应用程序图标右上角的数字UIUserNotificationTypeSound   = 1 << 1, 播放音效UIUserNotificationTypeAlert   = 1 << 2, 是否运行显示横幅*/[application setApplicationIconBadgeNumber:0];if (IS_iOS8) {UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];[application registerUserNotificationSettings:settings];}// 如果是正常启动应用程序,那么launchOptions参数是null,其他方式需要对launchOptions设置if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {// 当被杀死状态收到本地通知时执行的跳转代码// [self jumpToSession];UILabel *redView = [[UILabel alloc] init];redView.backgroundColor = [UIColor redColor];redView.frame = CGRectMake(0, 100, 300, 400);redView.numberOfLines = 0;redView.text = [NSString stringWithFormat:@"%@", launchOptions];[self.window.rootViewController.view addSubview:redView];}return YES;
}

远程推送

远程推送指从远程服务器推送给客户端的通知(需要联网),远程推送服务一般采用苹果的APNS (Apple Push Notification Service)。

要实现远程推送,一般会涉及到三个阶段:

  1. APNS Pusher应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。
  2. APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone。
  3. iPhone把发来的消息传递给相应的应用程序, 并且按照设定弹出Push通知。

基本配置

条件:新建一个对应你bundle的push 证书,打开Push Notifications 开关(XCode7不打开也可以正常使用,XCode8以后必须打开)。

代码实现:
注册接受APNs通知。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {// 1.注册UserNotification,以获取推送通知的权限UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];[application registerUserNotificationSettings:settings];// 2.注册远程推送[application registerForRemoteNotifications];} else {[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeNewsstandContentAvailability | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];}return YES;
}

调用AppDelegate方法,获取到用户的deviceToken。

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{// <32e7cf5f 8af9a8d4 2a3aaa76 7f3e9f8e 1f7ea8ff 39f50a2a e383528d 7ee9a4ea>// <32e7cf5f 8af9a8d4 2a3aaa76 7f3e9f8e 1f7ea8ff 39f50a2a e383528d 7ee9a4ea>NSLog(@"%@", deviceToken.description);
}

推送通知,和本地通知一样有两种状况。

// 当接受到远程退职时会执行该方法(当进入前台或者应用程序在前台)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{NSLog(@"%@", userInfo);UIView *redView = [[UIView alloc] init];redView.backgroundColor = [UIColor redColor];redView.frame = CGRectMake(100, 100, 100, 100);[self.window.rootViewController.view addSubview:redView];
}

苹果建议使用方法

/*1.开启后台模式2.调用completionHandler,告诉系统你现在是否有新的数据更新3.userInfo添加一个字段:"content-available" : "1" : 只要添加了该字段,接受到通知都会在后台运行*/
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{NSLog(@"%@", userInfo);UIView *redView = [[UIView alloc] init];redView.backgroundColor = [UIColor redColor];redView.frame = CGRectMake(100, 100, 100, 100);[self.window.rootViewController.view addSubview:redView];completionHandler(UIBackgroundFetchResultNewData);
}

UserNotitfication

iOS10 中统一了本地推送和远程推送的 API,在 UserNotifications.framework 来统一处理与推送相关任务,并增加了图片、音频、视频,自定义通知 UI 等新特性。

通知界面

多媒体

在此次版本中,iOS10 不仅新增消息的3dtouch等,还对图片、音频、视频等多媒体做了改进和优化。

类型 限制大小
图片 10M
音频 5M
视频 50M

多媒体推送代码:

if #available(iOS 10.0, *) {let content = UNMutableNotificationContent()content.title = "iOS10 推送测试"content.body = "附件"content.userInfo = ["icon":"1","mutable-content":1]content.categoryIdentifier = "InputSomething"let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)let requestIdentifier = "imageLocal"if let imageURL = Bundle.main.url(forResource: "avatar@2x", withExtension: "png"), let attachment = try? UNNotificationAttachment(identifier: "imageAttachment", url: imageURL, options: nil) {content.attachments = [attachment]}let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) inif (error != nil) {print("error: \(error.debugDescription)")}})}

通常在做多媒体自定义推送的时候,一般会用到UNNotificationServiceExtension应用扩展,通过在 payload 中增加 mutable-content 字段来触发扩展。

{"aps":{"alert":"IOS10 推送测试","sound":"default","badge":1,"mutable-content":1,"category":"InputSomething"},"image":"https://ws1.sinaimg.cn/mw690/934b5ef8gw1fapg2ssteej20oz0oz420.jpg"
}

当推送达到 app 时,会启动扩展并回调 didReceive 方法。在该方法里面可以对推送的 UNMutableNotificationContent 做出相应的修改。在 didReceive 回调方法中的 request 包含了推送的具体信息,可以通过其 userInfo 属性来解析出多媒体的 url。

let imageURL = Bundle.main.url(forResource: "lufei", withExtension: "jpg")

值得注意的是这里 Bundle 指的是扩展的沙盒,不是 app 的沙盒,所以资源的路径要正确。

而读取远程资源比读取本地资源一般要多一步保存操作。

private func downloadAndSave(url: URL, handler: @escaping (_ localURL: URL?) -> Void) {let task = URLSession.shared.dataTask(with: url, completionHandler: {data, res, error invar localURL: URL? = 下载完之后保存到本地并返回本地的 urlhandler(localURL)})task.resume()}

得到本地的 url 之后操作就一样了,都是通过 url 来生成一个 UNNotificationAttachment 对象。一切都操作完之后将这个 UNMutableNotificationContent 对象返还 contentHandler(bestAttemptContent)。

自定义界面

除了上述功能外,苹果还新增了自定义界面,这个绝对是大招。

其中上面的黄色区域可以理解成一个 ViewController 操作,下面绿色部分就是 Title 之类的显示内容。这部分是可以隐藏的。在扩展的目录下的 info.plist 编辑一些界面相关的东西。

说明:

  • UNNotificationExtensionCategory 触发 Extension 的 category
    这里需要在注册才能有效的触发 字符串类型
  • UNNotificationExtensionInitialContentSizeRatio 上图黄色区域的长宽比,float 类型
  • UNNotificationExtensionDefaultContentHidden 默认内容是否隐藏,Bool 类型

参考:ios 10.0之UserNotitfication

ios入门之消息推送详解相关推荐

  1. Web 实时消息推送详解

    title: Web 实时消息推送详解 category: 系统设计 head: meta name: keywords content: 消息推送,短轮询,长轮询,SSE,Websocket,MQT ...

  2. 关于Android安卓APP保活 - 安卓消息推送详解 - 安卓端外推送离线推送

    转自:http://zhangtielei.com/posts/blog-android-push.html 说Android端外推送比较烦,实际有两层意思:首先是说实现上比较麻烦,至今业界也没有找到 ...

  3. Spring4.3+Webscket 实现聊天、消息推送详解之具体实现(三)

    2019独角兽企业重金招聘Python工程师标准>>> 前面可能废话太多了,下面进入正题,讲解spring具体的实现方式. 先来说一下几个核心的步骤吧: 1.构建websocket服 ...

  4. iOS开发之消息推送 —— 远程消息推送入门

    每次看到iOS的远程消息推送,总是感觉很头大,即便后来项目都做完了,还是觉得摸不着远程推送的脉门,网上介绍的资料虽多,但不是写的太简单了,就是写的太详细了,不能一下抓住要点,今天终于能够抽出点时间,来 ...

  5. iOS 推送详解 push

    目录: 1.         Push机制的介绍 2.         Push机制的使用 3.         Push故障的排除 4.         Demo示例 Push机制 1. Push机 ...

  6. Java后端实现安卓/IOS移动端消息推送(百度云推送)

    本文主要介绍Java服务器端如何借助第三方推送平台(百度云推送)推送给移动端消息. 使用案例介绍: 根据客户的需求,需要做一个类似淘宝消息推送的功能,客户下订单.订单付款.订单商品已发货,以及客户完成 ...

  7. ios开发: APNS消息推送实现

    网上关于ios消息推送机制(APNS)的实现.原理介绍很多,但都零零散散. 昨天经过自己的多番尝试,终于成功实现了推送过程. 在此,贴上自己整理的印象笔记内容,包括自己实现过程中受益的内容链接,和遇到 ...

  8. php ajax 长轮询 表单,Thinkphp结合AJAX长轮询实现PC与APP推送详解

    前言 本文主要给大家介绍的关于Thinkphp结合AJAX长轮询实现PC与APP推送的相关内容,分享出来供大家参考学习,话不多说,来一起看看详细的介绍. 实现逻辑 某个操作(比如新建一条公告)后,触发 ...

  9. android极光推送no bit-32,iOS极光推送详解以及碰到问题和解决方式

    前言: 极光推送作为较成熟的推送平台,通过集成基础操作.为客户端以及服务端节省了大量时间来实现推送效果. ​ 就iOS端来说要注意整体流程,首先,iOS端推送时分为两个状态,开发环境与生产环境,每个环 ...

  10. IOS推送详解(一)------APNs

    最近项目需要做IOS推送,在网上了解了下苹果的推送过程以及接口协议. 博文会分几部分来写,先介绍下APNs,然后介绍协议(新的旧的都说下),然后介绍生成证书,最后上代码. APNS IOS推送要比安卓 ...

最新文章

  1. thinkphp5.1 中间件是什么有什么用
  2. 如何在 Linux 中创建一个共享目录
  3. Python判断一个字符串是否包含某个指定的字符串
  4. 一个最为简单的jquery 分页实现方法!可以用用于理解js分页的原理。
  5. 智能家居数据库设计_设计更智能的数据表
  6. python文件writelines_python 写文件write(string), writelines(list)
  7. Python 线程定时器 Timer - Python零基础入门教程
  8. 【SRH】------node创建简单的服务器
  9. linux 流场分析软件,scSTREAM | 通用流体分析软件
  10. 从入门到放弃C语言-入门篇(1)
  11. 基于Arduino的学习、记忆机械手
  12. 中国知网上html是什么意思,知网上网络首发是什么意思
  13. c语言 交互式电子白板案例,交互式电子白板案例分析
  14. MySQL8 NDB Cluster安装部署
  15. JVM 垃圾收集器Serial、Parallel Scavenge、ParNew、CMS、G1
  16. SAS实验04 ——回归分析
  17. 华为机试字符串分割c语言,2014年华为上机机试c语言标题和答案
  18. js使用input上传文件夹、拖拽上传文件夹并将文件夹结构展示为树形结构
  19. js实现字符串数组转换成数字数组
  20. php mysql抽奖转盘_PHP微信转盘抽奖前后台 数据库完整示例

热门文章

  1. VS2010开发环境之使用技巧
  2. 智能优化算法应用:基于GWO优化的对称交叉熵图像多阈值分割 - 附代码
  3. ValueError: Expected more than 1 value per channel when training, got input size torch.Size([1, 2, 1
  4. 【LeetCode】【refine 2】题号:*2. 两数相加
  5. matlab-lsqcurvefit函数 初始值选取
  6. ArcGIS 泛克里金插值
  7. 【ArcGIS|空间分析|网络分析】11 利用流量数据执行网络分析
  8. 对于 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针 的简单理解
  9. adnroid中LayoutParams的简单总结
  10. Flink 在快手实时多维分析场景的应用