IOS 推送通知 本地推送和远程推送

2023-05-16

什么是推送通知?

首先明确:**此处的推送通知跟我们的”NSNotification”没有半毛钱关系
可以理解为: 向用户推送一条信息来通知用户某件事情
作用: 可以在APP退到后台,或者关闭时;继续推送一条消息告诉用户某件事情

推送通知的应用场景?

  • (1) 一些任务管理APP,会在任务时间即将到达时,通知你做该任务;
    (2) 健身App定时提醒你应该健身了;
    (3) 买过电影票后,提前半小时告诉你,电影即将开场;
    (4) 当你QQ或者微信收到消息时,即使退到后台,或者关闭APP,也可以收到信息通知告诉我们;
    (5) 电商APP,推送一条消息通知我们有新品上架等等

推送通知的分类

  • 本地推送通知

    “本地”可以理解为”不联网”;即使没有网络情况下,也可以推送通知消息
    应用场景: 确定知道未来某个时间点应该提醒用户什么
    通知发送方:开发人员负责在app内部发送

  • 远程推送通知

    与“本地”相对,表示,必须在联网情况下才会向用户推送通知消息
    远程推送服务,又称为APNs(Apple Push Notification Services)

    应用场景:

    1. 不确定未来某个时间点应该提醒用户什么,临时性的
    2. 当APP彻底退出时也想继续让用户获取一些最新消息
  • 使用原则: 谁能确定通知时间和内容, 谁就可以发送(开发人员在APP内部通过代码发送=本地通知; 服务器可以确定通知时间和内容=远程通知)*

远程推送的呈现效果

image.png

本地推送通知

在iOS8.0之后 使用本地通知需要得到用户的许可 在didFinishLaunchingWithOptions里面添加请求

if(系统版本 >= 8.0)
{
    // 注册接收通知的类型
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [application registerUserNotificationSettings:settings];

    // 注册允许接收远程推送通知
    [application registerForRemoteNotifications];
}
else
{
    // 如果是iOS7.0,使用以下方法注册
    [application registerForRemoteNotificationTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound];
}

//swfit:

 if #available(iOS 8.0, *)
        {
            // 注册接收通知的类型
            let type = UIUserNotificationType.alert.rawValue | UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue
            let settings = UIUserNotificationSettings(types: UIUserNotificationType(rawValue: type), categories: nil)
            
            UIApplication.shared.registerUserNotificationSettings(settings)
            // 注册允许接收远程推送通知
            UIApplication.shared.registerForRemoteNotifications()
        }

发送一个本地通知

@IBAction func puchNotionfication(_ sender: Any)
    {
    // 如果是ios8.0以前, 以下代码, 可以直接发送一个本地通知,
    // 但是, 如果是ios8.0以后, 你需要主动的请求授权, 才可以
    // 通知显示的条件
    // 必须不能再前台
        
        //1.创建一个t本地通知
        let localNoti = UILocalNotification()
        //2. 设置通知内容
        localNoti.alertBody = "这是一个好日字"
        //3. 设置发送通知的时间触发时间
        localNoti.fireDate = Date(timeIntervalSinceNow: 4) 
    
        //重复周期
        // localNoti.repeatInterval = .weekday
        //设置滑动文字
        localNoti.hasAction = true
        localNoti.alertAction = "回复"
        // 启动图片(当用户点击了本地通知, 启动我们APP 的时候, 带的启动图片)
               // 如果是在ios9.0以前, 当锁屏界面, 出现一个通知, 用户点击了通知, 启动APP 的时候, 会自动将我们设置的图片, 当做启动图像 来显示
               // ios9.0, 这个属性, 不太灵
               // 如果这个图片,找不到, 会使用系统默认的启动图片
        localNoti.alertLaunchImage = "2"
        
        
               // 设置通知弹框的标题
               // 标题, 这对于, 通知中心的通知有效
        if #available(iOS 8.2, *)
        {
            localNoti.alertTitle = "斗地主"
        }

        // 设置图标右上角的数字(0 代表不显示)
        localNoti.applicationIconBadgeNumber = 3
         // userInfo 额外信息
        localNoti.userInfo = ["name":"哥哥", "sex":"女"]
        

    
        //应用程序级别的操作 ,调度本地通知,完成之后,会在特定的fireDate发出通知

        UIApplication.shared.scheduleLocalNotification(localNoti)
        
    }

其他的属性和方法

调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)
[[UIApplication sharedApplication] scheduleLocalNotification:ln];

获得被调度(定制)的所有本地推送通知
@property(nonatomic,copy) NSArray *scheduledLocalNotifications;
(已经发出且过期的推送通知就算调度结束,会自动从这个数组中移除)

取消调度本地推送通知
- (void)cancelLocalNotification:(UILocalNotification *)notification;
- (void)cancelAllLocalNotifications;

立即发出本地推送通知
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;


每隔多久重复发一次推送通知
@property(nonatomic) NSCalendarUnit repeatInterval;

点击推送通知打开app时显示的启动图片
@property(nonatomic,copy) NSString *alertLaunchImage;

附加的额外信息
@property(nonatomic,copy) NSDictionary *userInfo;

时区
@property(nonatomic,copy) NSTimeZone *timeZone;
(一般设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区)

点击本地通知

当用户点击本地推送通知,会自动打开app,这里有2种情况

  1. app并没有关闭,一直隐藏在后台
    让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
  1. app已经被关闭(进程已死)
    启动app,启动完毕会调用AppDelegate的下面方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
launchOptions参数通过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象

添加一些额外的操作

IMG_0497.PNG
func registerAuthor()
    {
        // Override point for customization after application launch.
           if #available(iOS 8.0, *)
           {
               // 注册接收通知的类型
               let type = UIUserNotificationType.alert.rawValue | UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue
            
               
            
            
            //1.创建z一组操作行为
            let category = UIMutableUserNotificationCategory()
            //1.1设置组标识
            category.identifier = "select"
            //1.2设置组里面的行为
            let action1 = UIMutableUserNotificationAction()
            action1.identifier = "queding"
            action1.title = "确定"
            // behavior todo
                       
            // 代表, 用户如果点击了这个动作, 拉到底, 是在前台运行这个动作, 还是在后台
            action1.activationMode = .foreground
             // 必须要解锁之后, 行为才会执行(如果activationMode, 是前台状态, 那这个属性, 就会被忽略)
            action1.isAuthenticationRequired = true
            // 是否是破坏性行为(会使用一个红色的标识, 来标识这个按钮)
            action1.isDestructive = false
            
            //1.1设置组标识
            category.identifier = "select"
            
            //1.2设置组里面的行为
            let action2 = UIMutableUserNotificationAction()
            action2.identifier = "huifu"
            action2.title = "回复"
            
            // behavior todo
            if #available(iOS 9.0, *)
            {
                action2.behavior = .textInput
                action2.parameters = [UIUserNotificationTextInputActionButtonTitleKey: "确定"]
                    
            }
                                      
            // 代表, 用户如果点击了这个动作, 拉到底, 是在前台运行这个动作, 还是在后台
            action2.activationMode = .background
            // 必须要解锁之后, 行为才会执行(如果activationMode, 是前台状态, 那这个属性, 就会被忽略)
            action2.isAuthenticationRequired = false
            // 是否是破坏性行为(会使用一个红色的标识, 来标识这个按钮)
            action2.isDestructive = false
            
            
            let actions = [action1, action2]
            
            // 如果针对于弹框样式的通知
            // default 代表, 最多可以显示4个按钮
            // minimal, 代表,最多可以显示2个按钮
            category.setActions(actions, for: .default)
            
            //附加操作行为组
            let categorys : Set<UIUserNotificationCategory> = [category]
            
               let settings = UIUserNotificationSettings(types: UIUserNotificationType(rawValue: type), categories: categorys)
                UIApplication.shared.registerUserNotificationSettings(settings)
            
               // 注册允许接收远程推送通知
               UIApplication.shared.registerForRemoteNotifications()
           }
               
        
    }
     // completionHandler, 系统提供的回调代码块, 执行这个代码块, 到时候, 系统会采集一些信息
    func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Void)
    {
        print(identifier,notification)
        print("old")
        completionHandler()
    }
    // 9.0
    // 如果实现了这个方法, 那么上面一个方法, 就不再执行
    func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
        print("new")
        print(identifier,responseInfo)
        completionHandler()
    }

远程推送

什么是远程推送通知

  • 顾名思义,就是从远程服务器推送给客户端的通知(需要联网)
  • 远程推送服务,又称为APNs(Apple Push Notification Services

为什么需要远程推送通知?

传统获取数据的局限性
只要用户关闭了app,就无法跟app的服务器沟通,无法从服务器上获得最新的数据内容
不管用户打开还是关闭app,只要联网了,都能接收到服务器推送的远程通知

所有的苹果设备,在联网状态下,都会与苹果的服务器建立长连接

  • 什么是长连接
    只要联网了,就一直建立连接

  • 长连接的作用
    时间校准
    系统升级
    查找我的iPhone
    .. ...

  • 长连接的好处
    数据传输速度快
    数据保持最新状态

获取deviceToken

苹果需要用户的UDID和bundleID

获取过程

qq案例分析

  1. app 发送设备的UDID和
    应用的Bundle Identifier
    给APNs服务器

  2. 经苹果加密生成一个
    deviceToken 返还给当前app

  3. app发送当前用户的deviceToken
    和用户的标志(比如id或者qq) 给qq服务器

  4. qq服务器将用户的deviceToken存进数据库

  5. 当有人发送消息 李四的手机(昵称:李四 QQ:56789)
    发给张三(QQ12345):吃饭没?

  6. 消息先到qq服务器,然后去数据库查询张三的deviceToken

  7. qq服务器通知苹果服务器
    deviceTokoen:888
    body:李四:吃饭没?

  8. 苹果服务器通过deviceToken找到张三现在的设备

一.开发iOS程序的推送功能, iOS端需要做的事

1.请求苹果获得deviceToken
2.得到苹果返回的deviceToken,发送deviceToken给公司的服务器

  1. 监听用户对通知的点击

二.调试iOS的远程推送功能, 必备条件:

1.真机

2.调试推送需要的证书文件
1> aps_development.cer : 某台电脑就能调试某个app的推送服务
2> iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序

三.发布具有推送服务的app

1> aps_production.cer : 如果发布的程序中包含了推送服务,就必须安装这个证书
2> qq.mobileprovision : 某台电脑就能发布某个程序

制作证书

截屏2020-05-27下午4.42.59.png
截屏2020-05-27下午4.43.18.png
截屏2020-05-27下午4.43.09.png
截屏2020-05-27下午4.43.25.png
截屏2020-05-27下午4.43.35.png
截屏2020-05-27下午4.43.44.png

注册远程推送通知

客户端如果想接收APNs的远程推送通知,必须先注册(得到用户的授权)
一般在App启动完毕后就马上注册

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // 注册远程通知
       UIRemoteNotificationType type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;
    [application registerForRemoteNotificationTypes:type];
    return YES;
}
  • 注册成功后会调用AppDelegate的下面方法,得到设备的deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"%@", deviceToken);
}

点击远程推送通知

当用户点击远程推送通知,会自动打开app,这里有2种情况
app并没有关闭,一直隐藏在后台
让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;

app已经被关闭(进程已死)
启动app,启动完毕会调用AppDelegate的下面方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
launchOptions参数通过UIApplicationLaunchOptionsRemoteNotificationKey取出服务器返回的字典内容
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

IOS 推送通知 本地推送和远程推送 的相关文章

随机推荐

  • 2021美团笔试题(第十套)个人解答

    1 淘汰分数 span class token comment 暴力解法 span span class token keyword import span span class token namespace java span clas
  • DeepSOCIAL:基于YOLOv4的人群距离监测!集检测、跟踪以及逆透视映射一体的系统!...

    点击下方 AI算法与图像处理 xff0c 一起进步 xff01 重磅干货 xff0c 第一时间送达 论文 xff1a https doi org 10 3390 app10217514 代码 xff1a https github com D
  • HAL 0.5.10 Specification

    HAL 0 5 10 Specification David Zeuthen lt a href david 64 fubar dk a gt Version 0 5 10 Table of Contents 1 Introduction
  • LINUX USB 系统(1) 收藏

    LINUX USB 系统 1 收藏 1 简述 xff1a USB 出自豪门 xff0c 一问世便有 IBM Microsoft compaq 等前呼后拥 xff0c 不红实在是没有道理 xff0c 以致于连三岁小毛孩都知道买游戏手柄要买 U
  • 高通brew 方案开机揭秘

    摘要 xff1a 本文试图通过代码来深入剖析 Qualcomm 手机开机的整个过程 xff0c 即从按下开机键一直到出现待机界面 xff0c Qualcomm 的手机软件在整个流程中究竟完成了哪些工作 本文的主要目标是理清手机的初始化流程
  • 编程之美读书笔记_3.3_计算字符串的相似度

    3 3 计算字符串的相似度 和计算两字符串的最长公共子序列相似 设Ai 为字符串A a1a2a3 am 的前i 个字符 xff08 即为a1 a2 a3 ai xff09 设Bj 为字符串B b1b2b3 bn 的前j 个字符 xff08
  • 有铅喷锡和无铅喷锡的选择

    有铅喷锡和无铅喷锡 xff08 SAC xff09 在生产中工艺要求是一个非常重要的因素 xff0c 他直接决定着一个PCB板的质量和定位 xff0c 比如喷锡 镀金 沉金 xff0c 相对来说沉金就是面对高端的板子 xff0c 沉金由于质
  • 硬盘的那些事(主分区、扩展分区、逻辑分区、活动分区、系统分区、启动分区、引导扇区、MBR等

    硬盘的那些事 xff08 主分区 扩展分区 逻辑分区 活动分区 系统分区 启动分区 引导扇区 MBR等 主分区 xff0c 扩展分区 xff0c 逻辑分区 xff0c 活动分区 xff0c 系统分区 xff0c 启动分区 主引导扇区 xff
  • Vcc(电源)和GND(地)之间接电容的作用

    1 在直流电源 xff08 Vcc xff09 和地之间并接电容的电容可称为滤波电容 xff0e 滤波电容滤除电源的杂波和交流成分 xff0c 压平滑脉动直流电 xff0c 储存电能 xff0e 取值一般100 xff0d 4700uF x
  • APM/Pixhawk地面站航迹规划指令单

    本文来源于http ardupilot org copter docs mission command list html condition distance 由于对APM Pixhawk的爱好 xff0c 翻译成中文供参考 xff0c
  • APM/Pixhawk路径规划飞行(自动起飞/降落/航路点飞行)

    APM Pixhawk路径规划飞行 xff08 自动起飞 降落 航路点飞行 xff09 本节主要介绍各类飞行器一般的航路点设置 xff0c 已经实现了自动起飞降落和按计划轨迹飞行 设置家的位置 对于直升机和多旋翼家的位置一般是飞控解锁的位置
  • E2上GBA模拟器移植的困难。。。

    终于决心动手写GBA的模拟器了 修改了半晌 xff0c 终于吧Oop的模拟器源码编译通过 xff0c 但是到了机器上却跑不起来 xff0c 那个源码用了一个非常奇怪的方式来处理系统响应 xff1a 主动调用系统去处理 xff0c 没开线程
  • 蓝牙物理链路类型:SCO和ACL链路

    蓝牙物理链路ACL Asynchronous Connectionless 另外的一种链路是SCO Synchronous Connection Oriented 主要用来传输对时间要求很高的数据通信 蓝牙基带技术支持两种连接类型 xff1
  • Linux内核角度分析tcpdump原理(二)

    上篇文章介绍了在内核角度tcpdump的抓包原理 1 xff0c 主要流程如下 xff1a 应用层通过libpcap库 xff1a 调用系统调用创建socket sock fd 61 socket PF PACKET SOCK RAW ht
  • 3 Linux目录管理

    注意 xff1a 在下面的讲解中 xff0c 每个命令都有很多的参数说明 选项 xff0c 我们只讲其中的几个 xff0c 关键是让学生掌握命令的语法 xff1b 学生学习完语法后 xff0c 就可以自己按照参数书写各种命令 xff0c 这
  • 多线程-读写安全

    多线程31 读写安全01 简介 文件操作 IO操作 读取文件 往文件中写入内容 不能允许读取和写入同时进行 我们之前做的加锁那种操作 xff0c 平时开发中有点缺陷我们最好让读的操作可以多条线程一起读取 多读单写 xff0c 多线程出乱主要
  • 单片机的程序具体运行过程以及栈空间的使用

    单片机的程序具体运行过程以及栈空间的使用 初始化RAM xff1a 将启动文件里选择的RAM空间清零 xff0c 将初始化不为零的全局变量在RAM里赋值 给PC指针赋初值 xff1a 将程序的第一条语句在ROM的地址取出给PC指针 程序执行
  • __block-内存管理

    我们创建一个对象如果我们block内部用到了 block类型的变量 xff0c 他会拥有这个对象 xff0c 我们可以通过cpp文件来分析 一旦访问对象 xff0c desc结构体里面就会多两个成员 xff0c 一个是copy 和dispo
  • 多线程 线程安全

    多线程的安全隐患 我们用多线程有很多好处 xff0c 但是也存在安全隐患 资源共享 1块资源可能会被多个线程共享 xff0c 也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象 同一个变量 同一个文件 当多个线程访问同一块资源时
  • IOS 推送通知 本地推送和远程推送

    什么是推送通知 首先明确 此处的推送通知跟我们的 NSNotification 没有半毛钱关系 可以理解为 向用户推送一条信息来通知用户某件事情 作用 可以在APP退到后台 或者关闭时 继续推送一条消息告诉用户某件事情 推送通知的应用场景