### 前言 笔者这几天刚完成《微言(官方版)》的推送功能,今天特分享一下在做的过程中实际解决的问题。如果读者你学到了有用的东西,希望能前往App Store下载《微言(官方版)》支持一下笔者,谢谢!?? 笔者使用的是用的比较广泛的**极光推送**,还有其他的什么百度推送、友盟推送等其实原理是一样的,至于选择哪个全凭读者喜好。说一下本文将要解决的几个问题: 1. APP处于前台运行状态,提示并接收保存消息; 2. APP处于后台运行状态,提示并接收保存消息; 3. APP处于退出状态,提示并接收保存消息。 ### 一、证书准备 关于推送证书的配置网上有很多的详细说明,这里不再赘述,推荐一篇比较好的博客 [iOS 推送通知 功能简单实现](http://www.jianshu.com/p/fda61af94d09) 。照着里面的步骤完成后,我们得到了这么几个文件: **四个证书**  前两个用于xcode的调试与发布  后两个用于极光推送的证书配置  **两个配置文件**  **一个带已配置远程推送的APP IDs文件**  ### 二、极光推送代码配置 iOS的代码配置笔者推荐最好去极光推送的官网去下载-> [Demo](https://docs.jiguang.cn/jpush/resources/) 。这里既然说是源码分享,所以贴上笔者的代码,仅供参考: AppDelegate.h ``` static NSString *appKey = @"*******************"; static NSString *channel = @"App Store"; static BOOL isProduction = TRUE; ``` AppDelegate.m ``` #import "AppDelegate.h" #import "JKChooseRootVCHelper.h" #import "JKUtilsHelper.h" #import "JKRemoteNoticeModel.h" // 引入JPush功能所需头文件 #import "JPUSHService.h" // iOS10注册APNs所需头文件 #ifdef NSFoundationversionNumber_iOS_9_x_Max #import <UserNotifications/UserNotifications.h> #endif - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; // 选择根控制器 [JKChooseRootVCHelper chooseRootViewController:self.window]; [self.window makeKeyAndVisible]; /******* 极光推送配置 ********/ // 获取自定义消息 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; [defaultCenter addObserver:self selector:@selector(NetworkDidReceivemessage:) name:kJPFNetworkDidReceiveMessageNotification object:nil]; // notice: 3.0.0及以后版本注册可以这样写,也可以继续用之前的注册方式 JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init]; entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound; if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { // 点击通知横幅启动app时获取APNS内容(代理方法也可以处理),可以在这里跳转到指定的界面 // NSDictionary *remoteNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey]; // NSInteger unReadCount = [[NSUserDefaults standardUserDefaults] integerForKey:kUnReadCount]; if (unReadCount == 0) { [UIApplication sharedApplication].applicationIconBadgeNumber = 0; } } [JPUSHService registerForRemoteNotificationConfig:entity delegate:self]; // 如不需要使用IDFA,advertisingIdentifier 可为nil [JPUSHService setupWithOption:launchOptions appKey:appKey channel:channel apsForProduction:isProduction advertisingIdentifier:nil]; /**************************/ return YES; } // 注册APNs成功并上报DeviceToken - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [JPUSHService registerDeviceToken:deviceToken]; JKLog(@"--Device Token: %@", deviceToken); } // 实现注册APNs失败接口(可选) - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { //Optional JKLog(@"--did Fail To Register For Remote Notifications With Error: %@", error); } #pragma mark- JPUSHRegisterDelegate // 前台收到 APNs 通知后就会走这个方法,iOS 10 Support - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler { // Required NSDictionary * userInfo = notification.request.content.userInfo; // UNNotificationRequest *request = notification.request; // 收到推送的请求 // UNNotificationContent *content = request.content; // 收到推送的消息内容 // // NSNumber *badge = content.badge; // 推送消息的角标 // NSString *body = content.body; // 推送消息体 // UNNotificationSound *sound = content.sound; // 推送消息的声音 // NSString *subtitle = content.subtitle; // 推送消息的副标题 // NSString *title = content.title; // 推送消息的标题 if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { [JPUSHService handleRemoteNotification:userInfo]; JKLog(@"--iOS10 前台收到远程通知:%@", userInfo); // [self logDic:userInfo] } else { // 判断为本地通知 // JKLog(@"--iOS10 前台收到本地通知:{\nbody:%@,\ntitle:%@,\nsubtitle:%@,\nbadge:%@,\nsound:%@,\nuserInfo:%@\n}", body,title,subtitle,badge,sound,userInfo); } completionHandler(UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以选择设置 // UNNotificationPresentationOptionBadge、UNNotificationPresentationOptionSound、UNNotificationPresentationOptionAlert } // 在前台点击通知消息后走该方法(即后台收到通知后,点击通知的回调方法),iOS 10 Support - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler { // Required NSDictionary * userInfo = response.notification.request.content.userInfo; // UNNotificationRequest *request = response.notification.request; // 收到推送的请求 // UNNotificationContent *content = request.content; // 收到推送的消息内容 // NSNumber *badge = content.badge; // 推送消息的角标 // NSString *body = content.body; // 推送消息体 // UNNotificationSound *sound = content.sound; // 推送消息的声音 // NSString *subtitle = content.subtitle; // 推送消息的副标题 // NSString *title = content.title; // 推送消息的标题 if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { [JPUSHService handleRemoteNotification:userInfo]; JKLog(@"--iOS10 前台收到远程通知:%@", userInfo); // [self logDic:userInfo] } else { // 判断为本地通知 // JKLog(@"--iOS10 前台收到本地通知:{\nbody:%@,\ntitle:%@,\nsubtitle:%@,\nbadge:%@,\nsound:%@,\nuserInfo:%@\n}", body,title,subtitle,badge,sound,userInfo); } completionHandler(); // 系统要求执行这个方法 } ``` 然后还得打开xcode的远程推送设置:  到这里,要说的 问题1 就实现了,现在APP在前端运行时能收到远程推送通知并能获取通知内容,但是当APP在后台