IOS_OC_本地推送知识总结

时间:2023-03-08 22:08:34

知识点介绍

一. 推送通知介绍(了解)

二. 本地推送通知

  1. 本地通知的基本使用
  2. 本地通知的不常用属性
  3. 删除重复的通知
  4. 通知的处理1-跳转界面
  5. 通知的处理2-程序退出
  6. 分类的设置/快捷回复

一. 推送通知介绍(了解)

  1. 推送通知的分类
  • 本地推送通知
  • 远程推送通知
  • 推送通知作用
    • 可以让不在前台运行的App告知用户App内部发生了什么事情
  • 推送通知效果
    • 屏幕顶部显示一个横幅
    • 屏幕中间弹出一个UIAertView
    • 锁屏时候也照样显示
    • 呈现的通知同时修改应用图标
    • 播放音效
    • 用户接受的推送通知都会展示在通知中心
  • 手机设置推送通知(自己看手机, 不解释)
  • 推送通知的使用细节
    • 发送通知时,如果应用程序正在前台运行,那么推送通知就不会显示出来
    • 点击推送通知默认会打开发送推送通知的应用
    • 不管应用是打开还是关闭,推送通知都可以如期发送

    二. 本地推送通知

    1. 本地通知的基本使用

    • 注册用户通知权限(只需一次, 可以单独放在Appdelegate中, 或者别的地方) —> iOS8以后必须, 需要用户授权才可以发送通知
    • 创建本地通知
    • 设置属性
    • 调度通知(添加通知到本地通知调度池)

    iOS7
    1.创建本地通知

    //创建本地通知
    [[UILocalNotification alloc]init]

    2.设置本地通知属性

      a.通知的内容   alertBody

      b.通知发送的时间   fireTime

      c.锁屏状态下滑块的文字  alertAction

      d.是否显示锁屏状态的滑块的文字 hasAction

      e.设置启动图片(随便指定)  alertLauchImage

      f.通知中心内部,该通知的标题  alertTitle

    //通知的内容
    localNotification.alertBody = @"你是猪么";
    //通知触发时间
    localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];
    //锁屏状态的下滑块文字
    localNotification.alertAction = @"猪";
    //是否显示锁屏状态的滑块文字
    localNotification.hasAction = NO;
    //通知中心显示的程序的名称
    localNotification.alertTitle = @"MK小月";

    (iOS 8.2 才有的)
      a.通知音效的名称  soundName  (一般都使用默认的)

      b.设置图标右上角的文字  applicationIconBadgeNumber

      c.重复的时间间隔   repeatInterval  (可以指定一个NSCalendarUnit)

      d.设置重复执行使用的日历  repeatCalendar

      e.设置额外信息  userInfo

    //通知音效的名称(静音状态是震动)
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    //设置图标右上角的文字
    localNotification.applicationIconBadgeNumber = ;
    //重复的时间间隔,可以指定一个NSCalendarUnit(最小是分钟)
    localNotification.repeatInterval = NSCalendarUnitMinute;
    //设置重复执行使用的日历
    localNotification.repeatCalendar;

    3.让应用调度本地通知

    //4. 将本地通知添加到系统的本地通知调度池中
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];

    4. 删除重复的通知

    //主要的目的是取消 一直重复的通知 (重复的通知会一直存在调度池中, 不消失)
    //删除单个通知
    - (IBAction)cancelLocalNotificationClick:(id)sender {
    //1. 获取之前的通知, 并删除
    NSArray *localNitifications = [[UIApplication sharedApplication] scheduledLocalNotifications]; NSLog(@"删除前: localNitifications: %@", localNitifications); //2. 循环遍历
    for (UILocalNotification *localNotification in localNitifications) { //3. 可以根据内容/通知的标示符删.
    NSString *userInfo = localNotification.userInfo[@"username"];
    NSLog(@"userinfo: %@", userInfo); if ([userInfo isEqualToString:@"男神"]) { [[UIApplication sharedApplication] cancelLocalNotification:localNotification];
    }
    } NSLog(@"删除后: localNitifications: %@", localNitifications);
    }
    //删除全部通知
    - (IBAction)cancelALLLocalNotificationClick:(id)sender {
    //如果有重复的通知, 都会被取消掉
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    }

    iOS8
    在应用程序启动的时候注册用户权限
    1.创建用户通知配置
      UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge |   UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];

    categories
       可以自定义通知的按钮,点击按钮可以执行后台或前台任务
       可以让我们提前准备好一些通知,使用的时候只需要指定使用category即可
    2.注册用户通知配置
      [application registerUserNotificationSettings:setting];

     //1. 请求授权
    // << 用于拼接选项用的
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
    //2.注册用户通知配置
    [application registerUserNotificationSettings:settings];

    4. 通知的处理1(跳转不同界面/前台不跳转)

    1.当用户进入某个区域的时候发送通知
     配置info文件
        NSLocationAlwaysUsageDescription
        NSLocationWhenInUseUsageDescription
    注册用户权限
        设置CLLocationManager的delegate
    监听用户授权的改变
      - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    子主题 5
    当接收到通知跳转到指定页面
    在AppDelegate中实现
      application:(UIApplication *)application didReceiveLocalNotification:
      方法在接收到本地通知的时候就会调用
      但是有时候,应用本来就在前台,进行跳转,影响用户体验,所以需要判断一下
      application.applicationState
      但是如果应用死掉了,通过点击通知启动应用就不会执行上面的代理方法了
      所以在方法:application:didFinishLaunchingWithOptions
      if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
    // 跳转界面
    }

    /**
    一. 通知的情况
    点击本地通知的时候, 会分成3种情况进行处理
    处理的目的, 就是获取不同的参数信息, 进行不同的逻辑处理(跳转不同的板块等) 1. 前台(程序在主界面显示) application:didReceiveLocalNotification:
    2. 后台(按住Home键退出后天/锁屏) application:didReceiveLocalNotification:
    3. 程序被杀死了 application: didFinishLaunchingWithOptions: 二. 处理的逻辑
    1. 前台/后台: application:didReceiveLocalNotification:
    1> 判断是否是前台(用户正在操作程序, 不应该直接发生跳转) 判断applicationState
    2> 根据程序的要求进行逻辑处理 (咱们当前的逻辑是调整不同的TabBar板块) 2. 程序退出: application: didFinishLaunchingWithOptions:
    1> 判断参数是否有值
    2> 获取通知, 并进行处理(不需要进行前台判断, 因为程序退出是一种单独的特殊状态) */ //当接收到本地通知后会调用
    //此方法, 前台/后台都可以接收到
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
    {
    /**
    UIApplicationStateActive, 激活(前台)
    UIApplicationStateBackground 后台
    */ //1. 如果是前台, 就不进行跳转
    if (application.applicationState == UIApplicationStateActive) {
    //将来可以提醒用户有新的消息
    return;
    } //2. 本地通知处理
    [self localNotification:notification];
    } - (void)localNotification:(UILocalNotification *)notification
    {
    //1. 获取TabBar,
    UITabBarController *tabBarC = (UITabBarController *)self.window.rootViewController; //2.在进行跳转.
    tabBarC.selectedIndex = [notification.userInfo[@"selectIndex"] integerValue];
    }
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    } //抢红包
    - (IBAction)changeToRedBaoClick:(id)sender { //目前的需求是切换根控制器的板块, 我们就简单的使用 1, 2来标识
    [self sendLocalNotificationWithAlertBody:@"有人发红包, 快去抢" userInfo:@{@"selectIndex" : @""}]; } //购物车
    - (IBAction)chageToBuyCarClick:(id)sender { [self sendLocalNotificationWithAlertBody:@"购物车没满, 快去抢" userInfo:@{@"selectIndex" : @""}];
    } //共用的发本地通知的代码 --> userinfo不一样 --> 将来可以根据userinfo进行区别处理
    - (void)sendLocalNotificationWithAlertBody:(NSString *)alertBody userInfo:(NSDictionary *)userinfo { //2. 创建本地通知
    UILocalNotification *localNotification = [UILocalNotification new]; //3. 设置本地通知的相关属性
    //3.1 触发时间
    localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:]; //3.2 内容
    localNotification.alertBody = alertBody; //3.3 声音(模拟器没有声音)(静音状态是震动)
    localNotification.soundName = UILocalNotificationDefaultSoundName; //3.4 应用程序角标
    localNotification.applicationIconBadgeNumber = ; //3.5 用户信息
    localNotification.userInfo = userinfo; //4. 将本地通知添加到系统的本地通知调度池中
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    }

    5. 通知的处理2(当程序退出时的处理)

    • 在应用程序启动时调用的方法中判断是否有通知的值
    • 获取本地通知信息
    • 自行处理逻辑
     二. 处理的逻辑
    . 前台/后台: application:didReceiveLocalNotification:
    > 判断是否是前台(用户正在操作程序, 不应该直接发生跳转) 判断applicationState
    > 根据程序的要求进行逻辑处理 (咱们当前的逻辑是调整不同的TabBar板块) . 程序退出: application: didFinishLaunchingWithOptions:
    > 判断参数是否有值
    > 获取通知, 并进行处理(不需要进行前台判断, 因为程序退出是一种单独的特殊状态) */ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //1. 请求授权 //1. 创建按钮
    //1.1 创建按钮1
    UIMutableUserNotificationAction *action1 = [UIMutableUserNotificationAction new];
    action1.identifier = @"Foreground";
    action1.title = @"好的";
    action1.activationMode = UIUserNotificationActivationModeForeground; //1.2 创建按钮2
    UIMutableUserNotificationAction *action2 = [UIMutableUserNotificationAction new];
    //为了区分不同的按钮点击, 增加的标示符
    action2.identifier = @"Background";
    action2.title = @"取消";
    action2.activationMode = UIUserNotificationActivationModeBackground; //如果想要实现iOS9自定义的文本框回复, 需要增加一个属性.
    action2.behavior = UIUserNotificationActionBehaviorTextInput; //2. 设置分类, 需要使用子类 UIUserNotificationCategory
    UIMutableUserNotificationCategory *category = [UIMutableUserNotificationCategory new];
    [category setActions:@[action1, action2] forContext:UIUserNotificationActionContextDefault]; //不同的本地通知, 可以有不同的响应处理. 为了区分不同的本地通知, 也需要增加标示符
    //这里的id, 需要和发送本地通知设置的category的值一致. 只有一致才能响应
    category.identifier = @"category"; //3. 设置权限, 并设置分类
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:[NSSet setWithObject:category]]; //4. 注册权限
    [application registerUserNotificationSettings:settings]; //程序退出 //1. 判断是否有本地通知的值
    if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey] != nil) { //2. 获取通知
    UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; //3. 本地通知处理
    [self localNotification:notification];
    }
    return YES;
    }

    6. 分类的使用

    • 发送通知时, 增加category来设置标示符
    #warning 这里的分类字符串, 一定要和在注册时的分类标示符一致 (category.identifier = @"category"
    
        localNotification.category = category;

    2.远程通知
    1.远程通知的使用场景与原理
    使用场景
       1.团购提醒
       2.游戏中的任务提醒
    原理
       短连接与长连接
       短连接
    概念
      当客户向服务器请求数据的时候建立连接,接受到服务端的数据后释放连接
    特点
      只有客户端向服务端请求数据,才能获得服务段的数据
    缺点:
      每次请求数据都需要通过三次握手建立连接,请求后需要四次握手协议释放连接,频繁数据传输效率较差
      不能实现推送服务
    优点:服务器的能够建立最大连接数量是有限的,可以更好利用服务器的连接资源
    使用场景
      绝大多数情况我们使用都是短连接
    长连接
    概念
      客户端与服务端建立起连接后就一直保持
    特点
      客户端可以给服务端发送数据,服务端也可以主动向客户端推送数据
    缺点
      连接后就占用了服务器的连接资源,如果长连接过多,会导致其他用户链接不上
    优点
      可实现推送服务
    使用场景
      时间校准
      系统升级
      查找我的iPhone
      ....
    整体原理图

    共享客户端deviceToken原理

    2.调试远程推送
      1.准备证书
      1.创建开发者证书(Developer)
      2.创一个可用与远程推送的App ID
      3.配置Development SSL Certificate
      必须与创建开发证书中使用的是同一个CertificateSigningRequest.certSigningRequest
      4.配置开发的Profile
    2.安装证书
      与上面生成证书的先后顺序一致
    3.客户端代码
      1.注册远程通知
    1.iOS8.0之前
    // 通知类型
      UIRemoteNotificationType type =   UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert;
    // 注册通知
      [application registerForRemoteNotificationTypes:type];
    2.iOS8之后(包含)
      UIUserNotificationSettings *remoteSetting = [UIUserNotificationSettings   settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil];
    // 注册通知权限
      [application registerUserNotificationSettings:remoteSetting];

    // 注册远程通知
      [application registerForRemoteNotifications];
    2.监听获取token的方法
    /**
    * 注册远程通知返回方法
    */
      - (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
      #warning 不要通过 [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding] 来创一个字符串,因为通过它创建的字符串为空
    // 正确的做法是使用description方法获取一个字符串
    NSString *token = deviceToken.description;
    // 服务端的使用的token是<ce190cfc 7c7bcff1 4b04d261 94632c57 ed00aee8 07d7cbd5 8bc43dbb 3d33cb86>
    // 去掉前后的连个"<"和">"

    4.发布远程推送App
    1.配置 Production SSL Certificate
    必须与创建开发证书中使用的是同一个CertificateSigningRequest.certSigningRequest
    2.创建发布证书
    3.创建发布的
    3.极光推送
    0.前提
    1.推送的开发证书
    2.产品证书
    1.下载SDK
    1.登陆网站,注册账号
    2.文档->资源下载

    3.下载iOS SDK

    2.根据入门指南实现推送功能
    1.转到入门指南->iOS集成指南

    2.SDK集成步骤
    1.创建应用
    1.页面

    2.转到个人账号管理中心->创建应用
    3.导出开发证书.p12->上传
    4.导出发布证书.p12->上传
    2.创建项目,导入SDK
    把lib文件夹拖入即可
    3.导入依赖的框架
    必须导入的框架Xcode6.3

    4.在Appdelegate中实现推送相关的方法
    3.常见错误
    profile与证书不匹配

    可能的情况
    1.生成profile的证书和你本地安装的证书不一致
    当一个账号多人使用的时候会出现这种情况,所以最好一个人负责账号管理,其他人使用p12文件
    2.开发证书只安装到系统证书中,在登录证书中没有
    解决:从系统证书中拷贝一份到登录里面
    3.开发证书在登录中有,但在系统中没有
    解决方案:从登录证书中拷贝一份到系统证书
    按住option键拖动也可以实现复制
    3.证书,AppID,设备ID,Profile都是正确
    但是如果你上次证书的profile的名字与这次相同,Xcode不会使用最新的
    解决方案:
    删除之前的缓存profile缓存
    缓存路径:
    /Users/用户名/Library/MobileDevice/Provisioning Profiles
    重新双击你profile
    1.发送本地通知
    iOS7
    1.创建本地通知
    [[UILocalNotification alloc] init]
    2.设置本地通知属性
    alertBody
    通知的内容
    fireTime
    通知发送的时间
    alertAction
    锁屏状态下滑块的文字
    hasAction
    是否显示锁屏状态的滑块的文字
    alertLauchImage
    设置启动图片(随便指定)
    alertTitle
    通知中心内部,该通知的标题
    (iOS 8.2 才有的)
    soundName
    通知音效的名称
    一般都使用默认的
    applicationIconBadgeNumber
    设置图标右上角的文字
    repeatInterval
    重复的时间间隔,可以指定一个NSCalendarUnit
    repeatCalendar
    设置重复执行使用的日历
    userInfo
    设置额外信息
    3.让应用调度本地通知
    [[UIApplication sharedApplication] scheduleLocalNotification:localNote];
    iOS8
    在应用程序启动的时候注册用户权限
    1.创建用户通知配置
    UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
    categories
    可以自定义通知的按钮,点击按钮可以执行后台或前台任务
    可以让我们提前准备好一些通知,使用的时候只需要指定使用category即可
    2.注册用户通知配置
    [application registerUserNotificationSettings:setting];
    3.当用户进入某个区域的时候发送通知
    配置info文件
    NSLocationAlwaysUsageDescription
    NSLocationWhenInUseUsageDescription
    注册用户权限
    设置CLLocationManager的delegate
    监听用户授权的改变
    - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    子主题 5
    当接收到通知跳转到指定页面
    在AppDelegate中实现
    application:(UIApplication *)application didReceiveLocalNotification:
    该方法在接收到本地通知的时候就会调用
    但是有时候,应用本来就在前台,进行跳转,影响用户体验,所以需要判断一下
    application.applicationState
    但是如果应用死掉了,通过点击通知启动应用就不会执行上面的代理方法了
    所以在方法:application:didFinishLaunchingWithOptions
    if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
    // 跳转界面

    }
    2.远程通知
    1.远程通知的使用场景与原理
    使用场景
    1.团购提醒
    2.游戏中的任务提醒
    原理
    短连接与长连接
    短连接
    概念
    当客户向服务器请求数据的时候建立连接,接受到服务端的数据后释放连接
    特点
    只有客户端向服务端请求数据,才能获得服务段的数据
    缺点:
    每次请求数据都需要通过三次握手建立连接,请求后需要四次握手协议释放连接,频繁数据传输效率较差
    不能实现推送服务
    优点:服务器的能够建立最大连接数量是有限的,可以更好利用服务器的连接资源
    使用场景
    绝大多数情况我们使用都是短连接
    长连接
    概念
    客户端与服务端建立起连接后就一直保持
    特点
    客户端可以给服务端发送数据,服务端也可以主动向客户端推送数据
    缺点
    连接后就占用了服务器的连接资源,如果长连接过多,会导致其他用户链接不上
    优点
    可实现推送服务
    使用场景
    时间校准
    系统升级
    查找我的iPhone
    ....
    整体原理图

    共享客户端deviceToken原理

    2.调试远程推送
    1.准备证书
    1.创建开发者证书(Developer)
    2.创一个可用与远程推送的App ID
    3.配置Development SSL Certificate
    必须与创建开发证书中使用的是同一个CertificateSigningRequest.certSigningRequest
    4.配置开发的Profile
    2.安装证书
    与上面生成证书的先后顺序一致
    3.客户端代码
    1.注册远程通知
    1.iOS8.0之前
    // 通知类型
    UIRemoteNotificationType type = UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert;
    // 注册通知
    [application registerForRemoteNotificationTypes:type];
    2.iOS8之后(包含)
    UIUserNotificationSettings *remoteSetting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil];
    // 注册通知权限
    [application registerUserNotificationSettings:remoteSetting];

    // 注册远程通知
    [application registerForRemoteNotifications];
    2.监听获取token的方法
    /**
    * 注册远程通知返回方法
    */
    - (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
    #warning 不要通过 [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding] 来创一个字符串,因为通过它创建的字符串为空
    // 正确的做法是使用description方法获取一个字符串
    NSString *token = deviceToken.description;
    // 服务端的使用的token是<ce190cfc 7c7bcff1 4b04d261 94632c57 ed00aee8 07d7cbd5 8bc43dbb 3d33cb86>
    // 去掉前后的连个"<"和">"

    4.发布远程推送App
    1.配置 Production SSL Certificate
    必须与创建开发证书中使用的是同一个CertificateSigningRequest.certSigningRequest
    2.创建发布证书
    3.创建发布的
    3.极光推送
    0.前提
    1.推送的开发证书
    2.产品证书
    1.下载SDK
    1.登陆网站,注册账号
    2.文档->资源下载

    3.下载iOS SDK

    2.根据入门指南实现推送功能
    1.转到入门指南->iOS集成指南

    2.SDK集成步骤
    1.创建应用
    1.页面

    2.转到个人账号管理中心->创建应用
    3.导出开发证书.p12->上传
    4.导出发布证书.p12->上传
    2.创建项目,导入SDK
    把lib文件夹拖入即可
    3.导入依赖的框架
    必须导入的框架Xcode6.3

    4.在Appdelegate中实现推送相关的方法
    3.常见错误
    profile与证书不匹配

    可能的情况
    1.生成profile的证书和你本地安装的证书不一致
    当一个账号多人使用的时候会出现这种情况,所以最好一个人负责账号管理,其他人使用p12文件
    2.开发证书只安装到系统证书中,在登录证书中没有
    解决:从系统证书中拷贝一份到登录里面
    3.开发证书在登录中有,但在系统中没有
    解决方案:从登录证书中拷贝一份到系统证书
    按住option键拖动也可以实现复制
    3.证书,AppID,设备ID,Profile都是正确
    但是如果你上次证书的profile的名字与这次相同,Xcode不会使用最新的
    解决方案:
    删除之前的缓存profile缓存
    缓存路径:
    /Users/用户名/Library/MobileDevice/Provisioning Profiles
    重新双击你profile