手把手教你实现iOS 远程推送
当我们的手机在关闭状态下仍然能收到各种通知,那是我们下载安装的App主动提示到来的新信息,下面是我手机通知中心的部分截图:

众说周知,iOS远程推送通过APNs实现。APNs是Apple Push Notification service的简称,它由Apple独家提供。远程推送的服务的实现依据的是服务器和客户端的长连接,信息通过服务器主动推送(push)给客户端(我们的手机)。其中Android基于开源的理念,推送策略由第三方自定义,方便的同时也造成了市场上推送技术五花八门的存在。而iOS的推送必须通过Apple的服务器来实现,虽然市面上常用的有极光,环信,融云等第三方的存在,但是它们都是基于Apple的APNs, 优化集成推送的前端工作,最后仍然需要将推送证书和设备标志DeviceToken发送给Apple的服务器来实现远程推送。
制作推送证书
iOS工程开发指引中对推送流程的概括如下

服务端的Provider通过APNs将信息推送给Client App经过两步:
1 Provider -> APNs //需要苹果机构颁发的证书
2 APNs -> Client //需要DeviceToken标志App
制作证书之前,介绍一下iOS的设计理念: 基于闭环和安全的思考,苹果公司要求使用APNs服务的开发者,提供开发时的Mac设备、App的ID和运行App的手机,通过对三者的联合检查,基本上能保证确认App的唯一性,保证对AppStore的管理的安全性和可靠性。
首先,我们在苹果开发者中心,注册自己的App的唯一ID:

继续直至Done.
然后制作和AppID相绑定的CER证书

点击continue:

点击continue,能够看到需要创建CSR证书,下面有详细创建步骤,这一步可以绑定开发设备Mac。英文很简单,和创建发布证书时在「钥匙串访问」中的操作一样。

在「钥匙串访问」中能得到CSR文件

上传CSR文件

直至Done,下载CER文件:

双击安装到本机Mac。

在「钥匙串访问」我的证书中,能看到安装后的结果:

可以将证书导出,单独存放。以后别人需要,方便直接发送。
打开AppID的PushNotification功能


现在,证书已经制作好了,然后我们在对应的工程中愉快的使用了。
在工程中使用证书
确认Target的Identify和Signing:

iOS10中,改进了推送的代理方法,增加了3DTouch效果。下面以iOS10的新方法在AppDelegate添加接受通知的代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (@available(iOS 10.0, *)) {
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionBadge|UNAuthorizationOptionSound|UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSLog(@"%@", error);
}];
UNNotificationCategory* generalCategory = [UNNotificationCategory
categoryWithIdentifier:@"GENERAL"
actions:@[]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
// Create the custom actions for expired timer notifications.
UNNotificationAction* snoozeAction = [UNNotificationAction
actionWithIdentifier:@"SNOOZE_ACTION"
title:@"Snooze"
options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction* stopAction = [UNNotificationAction
actionWithIdentifier:@"STOP_ACTION"
title:@"Stop"
options:UNNotificationActionOptionDestructive];
UNNotificationAction* forAction = [UNNotificationAction
actionWithIdentifier:@"FOR_ACTION"
title:@"forAction"
options:UNNotificationActionOptionForeground];
// Create the category with the custom actions.
UNNotificationCategory* expiredCategory = [UNNotificationCategory
categoryWithIdentifier:@"TIMER_EXPIRED"
actions:@[snoozeAction, stopAction,forAction]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionNone];
// Register the notification categories.
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center setDelegate:self];
[center setNotificationCategories:[NSSet setWithObjects:generalCategory, expiredCategory,
nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
} else {
}
return YES;
}
#pragma mark - UNUserNotificationCenterDelegate
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(@"%s", __func__);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler{
NSLog(@"%s", __func__);
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
//保存deviceToken
NSLog(@"regisger success:%@",pToken);
}
iOS的远程推送需要在真机上调试,如果注册成功,就能在didRegisterForRemoteNotificationsWithDeviceToken方法中获取APNs返回的DeviceToken,在打印栏可以看到。
使用SmartPush调试
使用SmartPush可以在电脑上方便的模拟APNs推送。运行程序,选择我们生成的证书和填上打印栏获得的DeviceToken,就能在我们的App中看到APNs推送来的带有3DTouch功能的通知。

喜欢和关注都是对我的鼓励和支持~
参考文档:
http://www.jianshu.com/p/5a4b88874f3a
http://blog.csdn.net/showhilllee/article/details/8631734
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1