一、注册推送:

- (void)registerNotification

{

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0)

{

if (@available(iOS 10.0, *)) {

UNUserNotificationCenter * center =[UNUserNotificationCenter currentNotificationCenter];

center.delegate=self;

UNAuthorizationOptions options = UNAuthorizationOptionAlert|UNAuthorizationOptionSound|UNAuthorizationOptionBadge|UNAuthorizationOptionCarPlay;

[center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError * _Nullable error) {

if (granted) {

}else{

NSLog(@"授权失败");

}

}];

} else {

// Fallback on earlier versions

}

}

else if ([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0)

{

UIUserNotificationSettings *sets= [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound) categories:nil];

[[UIApplication sharedApplication] registerUserNotificationSettings:sets];

}

else

{

UIRemoteNotificationType type = UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound;

[[UIApplication sharedApplication] registerForRemoteNotificationTypes:type];

}

[[UIApplication sharedApplication] registerForRemoteNotifications];

}

假如用户第一次安装拒绝推送需要提醒的,按以下方法:(例子:iOS10 )

    UNUserNotificationCenter *userNotificationCenter = [UNUserNotificationCenter currentNotificationCenter];

userNotificationCenter.delegate = self;

//获取通知设置信息

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

//用户还未做出选择

if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {

//弹出授权框

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

if (granted) {

}else{

//首次授权为未授权状态,之后为已授权状态

DLog(@"没有开启通知");

}

}];

}else if (settings.authorizationStatus == UNAuthorizationStatusDenied){

//用户不同意授权时,弹出提示(最好只弹一次)

UIAlertController *noticeNotificationAlertController = [UIAlertController alertControllerWithTitle:@"友情提示" message:@"建议您开启通知功能,以便及时获取相关信息" preferredStyle:UIAlertControllerStyleAlert];

[noticeNotificationAlertController addAction:[UIAlertAction actionWithTitle:@"忽略" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

}]];

[noticeNotificationAlertController addAction:[UIAlertAction actionWithTitle:@"去开启" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {

NSURL *appSettingsUrl = [NSURL URLWithString:UIApplicationOpenSettingsURLString];

if ([[UIApplication sharedApplication] canOpenURL:appSettingsUrl]) {

[[UIApplication sharedApplication] openURL:appSettingsUrl];

}

}]];

[self.window.rootViewController presentViewController:noticeNotificationAlertController animated:YES completion:NULL];

}else{

//已授权

DLog(@"已授权通知");

}

}];

二、本地推送:

iOS10之后:

//使用 UNNotification 本地通知

+(void)registerNotification:(NSInteger )alerTime{

// 使用 UNUserNotificationCenter 来管理通知

UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];

//需创建一个包含待通知内容的 UNMutableNotificationContent 对象,注意不是 UNNotificationContent ,此对象为不可变对象。

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

content.title = [NSString localizedUserNotificationStringForKey:@"Hello!" arguments:nil];

content.body = [NSString localizedUserNotificationStringForKey:@"Hello_message_body"

arguments:nil];

content.sound = [UNNotificationSound defaultSound];

// 在 alertTime 后推送本地推送

UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger

triggerWithTimeInterval:alerTime repeats:NO];

UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"FiveSecond"

content:content trigger:trigger];

//添加推送成功后的处理!

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

UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"本地通知" message:@"成功添加推送" preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];

[alert addAction:cancelAction];

[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alert animated:YES completion:nil];

}];

}

iOS10以前:

+ (void)registerLocalNotificationInOldWay:(NSInteger)alertTime {

UILocalNotification *notification = [[UILocalNotification alloc] init];

// 设置触发通知的时间

NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:alertTime];

NSLog(@"fireDate=%@",fireDate);

notification.fireDate = fireDate;

// 时区

notification.timeZone = [NSTimeZone defaultTimeZone];

// 设置重复的间隔

notification.repeatInterval = kCFCalendarUnitSecond;

// 通知内容

notification.alertBody =  @"该起床了...";

notification.applicationIconBadgeNumber = 1;

// 通知被触发时播放的声音

notification.soundName = UILocalNotificationDefaultSoundName;

// 通知参数

NSDictionary *userDict = [NSDictionary dictionaryWithObject:@"开始学习iOS开发了" forKey:@"key"];

notification.userInfo = userDict;

// 通知重复提示的单位,可以是天、周、月

notification.repeatInterval = NSDayCalendarUnit;

// 将本地通知添加到调度池,定时发送

[[UIApplication sharedApplication] scheduleLocalNotification:notification];

  // 立即发送

// [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];

}

本地通知相关代理方法:

// 当App在前台状态下,如果有通知会调用该方法

// 当应用程序在后台状态下,点击推送通知,程序从后台进入前台后,会调用该方法(从锁屏界面点击推送通知从后台进入前台也会执行)

// 当应用程序完全退出时不调用该方法

- (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification{

  NSLog(@"%@", notification);

  // 处理点击通知后对应的业务

  UIApplicationState applicationState = [[UIApplication sharedApplication] applicationState];

   if (applicationState == UIApplicationStateActive) {

  // 前台

  // 例如QQ会增加tabBar上的badgeValue未读数量

  }

  else if (applicationState == UIApplicationStateInactive) {

  // 从前台进入后台

  // 例如QQ会打开对应的聊天窗口

  NSInteger applicationIconBadgeNumber = application.applicationIconBadgeNumber - 1;

  application.applicationIconBadgeNumber = applicationIconBadgeNumber >= 0 ? applicationIconBadgeNumber : 0;

  }

   [application cancelLocalNotification:notification];

}

// 监听附加操作按钮

- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(nonnull UILocalNotification *)notification completionHandler:(nonnull void (^)())completionHandler {

  NSLog(@"identifier:%@", identifier); completionHandler();

}

// 该方法在iOS9.0后调用,iOS9.0之前调用上面那个方法

- (void)application:(UIApplication *)app handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(nonnull UILocalNotification *)notification withResponseInfo:(nonnull NSDictionary *)responseInfo completionHandler:(nonnull void (^)())completionHandler {

  // ====identifier:no, content:{UIUserNotificationActionResponseTypedTextKey = "not agree";}

  NSLog(@"====identifier:%@, content:%@", identifier, responseInfo);

  completionHandler();

}

三、远程通知:

1、什么是远程推送

在联网的情况下,由远程服务器推送给客户端的通知,又称APNs(Apple Push Notification Services)不管应用是打开还是关闭的情况下,都能接收到服务器推送的远程通知在联网状态下,所有苹果设备都会与苹果服务器建立长连接

2、远程推送的实现原理:

1.打开App时: 发送UDIDBundleIDAPNs加密后返回deviceToken

2.获取Token后,App调用接口,将用户身份信息和deviceToken发给服务器,服务器记录

3.当推送消息时, 服务器按照用户身份信息找到存储的deviceToken,将消息和deviToken发送给APNs

4.苹果的APNs通过deviceToken, 找到指定设备的指定程序, 并将消息推送给用户

3、实现远程推送功能的前提

1.真机

2.调试阶段的证书

 iOS_development.cer 用于真机调试的证书

aps_development.cer 用于真机推送调试能的证书

xxx.mobileprovision 描述文件,记录了能够调试的手机、电脑和程序

3.发布阶段的证书

iOS_distribution.cer 用于发布app的证书

aps.cer 用于发布时,让app有推送功能的证书

xxx.mobileprovision 描述文件,记录了能够发布app的电脑

如何配置证书, 不在本教程内, 请读者自行处理, 或者参考视频教程

一、 注册远程推送并获取DeviceToken

1.创建iOS的项目,并输入项目名字

2.在AppDelegate中导入头文件:

#import <UserNotifications/UserNotifications.h>

3.在application:didFinishLaunchingWithOptions方法中, 注册远程通知

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

 {

 //请求通知权限, 本地和远程共用

 UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

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

  if(granted) {

   NSLog(@"请求成功");

    } else{

    NSLog(@"请求失败");

    }

   }];

 //注册远程通知

 [[UIApplication sharedApplication] registerForRemoteNotifications];

 //设置通知的代理

 center.delegate = self;

 returnYES;

 }

4.在接收远程推送的DeviceToken方法中, 获取Token

1

2

3

4

5

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

{

//将来需要将此Token上传给后台服务器

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

}

二、 iOS10之前通知的处理方法

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

{

  //此方法已被下面的方法代替

}

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

{

   //iOS10之前,接收远程通知时,不管在前台、后台还是程序杀死都会调用此方法

  if (application.applicationState == UIApplicationStateActive) {

  // 前台收到通知处理

  }else{

  //后台或退出时点击通知处理

  }

      completionHandler();

}

三、 iOS10远程推送通知的处理方法

当点击了推送后, 如果你希望进行处理. 那么在iOS10中, 还需要设置UNUserNotificationCenterdelegate, 并遵守UNUserNotificationCenterDelegate协议.

以及实现下面实现3个方法, 用于处理点击通知时的不同情况的处理

willPresentNotification:withCompletionHandler 用于前台运行

didReceiveNotificationResponse:withCompletionHandler 用于后台及程序退出

didReceiveRemoteNotification:fetchCompletionHandler用于静默推送

?

1

2

//设置通知的代理

center.delegate = self;

1.前台运行 会调用的方法

前台运行: 指的是程序正在运行中, 用户能看见程序的界面.

iOS10会出现通知横幅, 而在以前的框架中, 前台运行时, 不会出现通知的横幅.

?

1

2

3

4

5

6

7

8

9

10

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

 {

  NSDictionary *userInfo = notification.request.content.userInfo;

  //前台运行推送 显示红色Label
  [self showLabelWithUserInfo:userInfo color:[UIColor redColor]];
  //可以设置当收到通知后, 有哪些效果呈现(声音/提醒/数字角标)
  completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
 }

2.后台运行及程序退出 会调用的方法

后台运行: 指的是程序已经打开, 用户看不见程序的界面, 如锁屏和按Home键.

程序退出: 指的是程序没有运行, 或者通过双击Home键,关闭了程序.

1
2
3
4
5
6
7
8
9
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler
 {
  NSDictionary *userInfo = response.notification.request.content.userInfo;
 
  //后台及退出推送 显示绿色Label
  [self showLabelWithUserInfo:userInfo color:[UIColor greenColor]];
 
  completionHandler();
 }

3.静默推送通知 会调用的方法

静默推送: iOS7以后出现, 不会出现提醒及声音.

要求:

推送的payload中不能包含alertsound字段

需要添加content-available字段, 并设置值为1

例如: {"aps":{"content-available":"1"},"PageKey”":"2"}

1
2
3
4
5
6
7
8
//如果是以前的旧框架, 此方法 前台/后台/退出/静默推送都可以处理
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  //静默推送 显示蓝色Label
 [self showLabelWithUserInfo:userInfo color:[UIColor blueColor]];
 
 completionHandler(UIBackgroundFetchResultNewData);
 }

4.处理通知的公用方法

开发中, 点击通知的逻辑应当看自己程序的需求.

这里为了方便演示, 简单的将通知的值, 通过UILabel显示在主界面上.

1
2
3
4
5
6
7
8
9
- (void)showLabelWithUserInfo:(NSDictionary *)userInfo color:(UIColor *)color
{
 UILabel *label = [UILabel new];
 label.backgroundColor = color;
 label.frame = CGRectMake(0, 250, [UIScreen mainScreen].bounds.size.width, 300);
 label.text = userInfo.description;
 label.numberOfLines = 0;
 [[UIApplication sharedApplication].keyWindow addSubview:label];
}

iOS推送,看这篇足够了的更多相关文章

  1. 基于APNs最新HTTP/2接口实现iOS的高性能消息推送(服务端篇)

    1.前言 本文要分享的消息推送指的是当iOS端APP被关闭或者处于后台时,还能收到消息/信息/指令的能力. 这种在APP处于后台或关闭情况下的消息推送能力,通常在以下场景下非常有用: 1)IM即时通讯 ...

  2. iOS 推送全解析

    本文旨在对 iOS 推送(以下简称 推送)进行一个完整的剖析,如果你之前对推送一无所知,那么在你认真地阅读了全文后必将变成一个推送老手,你将会对其中的各种细节和原理有充分的理解.以下是 pikacod ...

  3. 一步一步教你做ios推送

    最近在研究ios的推送问题,遇到了一些问题,最终整理了一下.放在这里和大家分享 APNS的推送机制 首先我们看一下苹果官方给出的对ios推送机制的解释.如下图 Provider就是我们自己程序的后台服 ...

  4. iOS 推送全解析,你不可不知的所有 Tips!

    本文旨在对 iOS 推送进行一个完整的剖析,如果你之前对推送一无所知,那么在你认真地阅读了全文后必将变成一个推送老手,你将会对其中的各种细节和原理有充分的理解.以下是 pikacode 使用 iOS ...

  5. IOS 推送-配置与代码编写

    IOS 推送配置与代码编写 这里介绍IOS的推送,本文章已经在IOS6/7/8上都能运行OK,按照道理IOS9应该没问题. 大纲: 1.文章前提 2.推送介绍 3.推送文件账号设置 4.推送证书介绍 ...

  6. “iOS 推送通知”详解:从创建到设置到运行

    这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...

  7. iOS推送 再备

    这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...

  8. 利用pyapns进行ios推送

    ios客户端的同事提供了2个证书,分别是aps_development.cer  和 pushdevelopment.p12, 我最终目的就是把这2个证书合并成1个pem证书,然后通过pyapns进行 ...

  9. iOS推送的众多坑

    新来的一家公司,昨天和同事解决推送问题(工程里有集成百度推送和环信即时通讯),信誓旦旦的声称:" app在前台和后台运行时,推送触发的是didReceiveRemoteNotificatio ...

  10. iOS 推送问题全解答《十万个为啥吖?》

    Q 1:为啥收不到推送(1)? 如果收到推送时,App 在前台运行,那么: iOS 10 before 顶部横幅不会弹出.没有任何展示,你以为「没有收到推送」. iOS 10 after 如果没有实现 ...

随机推荐

  1. springboot高并发redis细粒度加锁(key粒度加锁)

    本文探讨在web开发中如何解决并发访问带来的数据同步问题. 1.需求: 通过REST接口请求并发访问redis,例如:将key=fusor:${order_id} 中的值+1: 2.场景: 设想,多线 ...

  2. scala配置intellij IDEA15.0.3环境及hello world!

    1. Intellij IDEA Scala开发环境搭建 Intellij IDEA 15.0.3 默认配置里面没有Scala插件,需要手动安装,在Intellij IDEA 15.0.3 第一次运行 ...

  3. Logcat monkey命令

    1. monkey命令 adb shell monkey -p com.autonavi.gxdtaojin --bugreport --ignore-crashes --ignore-timeout ...

  4. 虚拟机VMware Workstation Pro下安装ubuntu-14.04.4(64位)方法(附ubuntu-14.04-desktop-amd64.iso下载链接)

    ubuntu-14.04-desktop-amd64.iso下载: 链接:http://pan.baidu.com/s/1bFi0d4 密码:yx0l 零基础linux使用入门教学视频分享: 链接:h ...

  5. Nginx防盗链的3种方法

    一:一般的防盗链如下: location ~* \.(gif|jpg|png|swf|flv)$ { valid_referers none blocked www.jzxue.com jzxue.c ...

  6. 如何学习LoadRunner性能测试?

    最近组内同事针对性能测试LR的脚本部分做了介绍,是个不错的分享.会后反思自己也有很长一段时间没做性能测试了,根据以往的经验,有必要做些整理和补充,本文主要介绍一些Loadrunner性能测试的学习方法 ...

  7. OMP算法代码学习

    正交匹配追踪(OMP)算法的MATLAB函数代码并给出单次测试例程代码 测量数M与重构成功概率关系曲线绘制例程代码 信号稀疏度K与重构成功概率关系曲线绘制例程代码   参考来源:http://blog ...

  8. web前端——10个妨碍进步的学习方式

    1.前言 从事web前端的人很多,每个人的学习方式,学习习惯基本不会一模一样!关于web前端(或者直接互联网),大家都知道,是做到老,学到老的一个行业.之前写文章的时候,我说过很多学习的方式和建议.今 ...

  9. MongoDB索引限制

    1. 额外开销: 每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作.所以,如果你很少对集合进行读取操作,建议不使用索引. 2. 内存使用: 由于索引是存储在内存(RAM)中 ...

  10. Vue源码后记-其余内置指令(3)

    其实吧,写这些后记我才真正了解到vue源码的精髓,之前的跑源码跟闹着玩一样. go! 之前将AST转换成了render函数,跳出来后,由于仍是字符串,所以调用了makeFunction将其转换成了真正 ...