diff --git "a/IOS\346\216\250\351\200\201\345\210\206\344\272\253" "b/IOS\346\216\250\351\200\201\345\210\206\344\272\253"
new file mode 100644
index 0000000..44c4399
--- /dev/null
+++ "b/IOS\346\216\250\351\200\201\345\210\206\344\272\253"
@@ -0,0 +1,130 @@
+消息推送
+APNS的推送机制
+首先我们看一下苹果官方给出的对IOS推送机制的解释。如下图
+
+Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的缩写,也就是苹果的推送服务器。
+上图可以分为三个阶段:
+第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。
+第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
+第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
+
+
+
+
+APNS推送通知的详细工作流程
+下面这张图是说明APNS推送通知的详细工作流程:
+
+
+根据图片我们可以概括一下:
+1、应用程序注册APNS消息推送。
+2、IOS从APNS Server获取devicetoken,应用程序接收device token。
+3、应用程序将device token发送给程序的PUSH服务端程序。
+4、服务端程序向APNS服务发送消息。
+5、APNS服务将消息发送给iPhone应用程序。
+
+
+客户端实现起来相对容易,但后台要支持APNS的话还是比较复杂的,因此,我使用口碑较好的第三方推送-极光推送。
+准备工作
+1, 申请推送证书
+http://www.2cto.com/kf/201604/500620.html
+2, 将推送证书导出为p12文件,并上传至极光推送
+3, 导入JPUSH框架
+xcode 8以下 建议手动导入JPUSH,由于缺少系统库UserNotifications.framework会导致框架无法使用
+• 在极光官网下载最新SDK
+• 将SDK包解压,在Xcode中选择“Add files to 'Your project name'...”,将解压后的lib子文件夹(包含JPUSHService.h、jpush-ios-x.x.x.a、jcore-ios-x.x.x.a)添加到你的工程目录中。
+• 添加Framework
+o CFNetwork.framework
+o CoreFoundation.framework
+o CoreTelephony.framework
+o SystemConfiguration.framework
+o CoreGraphics.framework
+o Foundation.framework
+o UIKit.framework
+o Security.framework
+o libz.tbd (Xcode7以下版本是libz.dylib)
+o AdSupport.framework (获取IDFA需要;如果不使用IDFA,请不要添加)
+o UserNotifications.framework (Xcode8及以上)
+o libresolv.tbd (JPush 2.2.0及以上版本需要, Xcode7以下版本是libresolv.dylib)
+• 设置 Search Paths 下的 User Header Search Paths 和 Library Search Paths,比如SDK文件夹(默认为lib)与工程文件在同一级目录下,则都设置为"$(SRCROOT)/{静态库所在文件夹名称}"即可。
+允许Xcode7支持Http传输方法
+如果您使用的是2.1.9及以上的版本则不需要配置此步骤
+如果用的是Xcode7或更新版本,需要在App项目的plist手动配置下key和值以支持http传输:
+选择1:根据域名配置
+• 在项目的info.plist中添加一个Key:NSAppTransportSecurity,类型为字典类型。
+• 然后给它添加一个NSExceptionDomains,类型为字典类型;
+• 把需要的支持的域添加給NSExceptionDomains。其中jpush.cn作为Key,类型为字典类型。
+• 每个域下面需要设置2个属性:NSIncludesSubdomains、NSExceptionAllowsInsecureHTTPLoads。 两个属性均为Boolean类型,值分别为YES、YES。
+如图:
+
+选择2:全局配置
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+
+
+
+代码集成
+
+
+初始化JPUSH, types属性设置收到通知时,APP的一些相应方式,包括bageValue,提示音或者震动,来提示用户接收到通知。在XCODE8以下,由于缺少UserNotifications.framework框架,所以无法使用IOS的特性,而极光的代理属性洽洽需要配合UserNotifications才能使用,因此此处传nil即可。
+appKey:极光开发者后台提供,你可以通过注册账号并创建应用获得
+channel:通常为Publish channel
+func setPushNoti(launchOptions:[NSObject: AnyObject]?){
+ //setup apns
+ let entity = JPUSHRegisterEntity()
+ entity.types = (1 << 0) | (1 << 1) | (1 << 2)
+ JPUSHService.registerForRemoteNotificationConfig(entity, delegate: nil)
+
+ //set jpush
+ JPUSHService.setupWithOption(launchOptions, appKey: K_APP_KEY, channel: K_CHANNEL, apsForProduction: false)
+ setJPUSH()
+ }
+
+依次添加以下代码
+func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData){
+ JPUSHService.registerDeviceToken(deviceToken)
+ }//将苹果通知中心的deviceToken返回给极光推送后台
+
+func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError){
+ print("注册apns失败 \n \(error.localizedDescription)")
+ }//当然了,你需要关键的LOG
+
+func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
+ JPUSHService.handleRemoteNotification(userInfo)
+ completionHandler(UIBackgroundFetchResult.NewData)
+ print("ios7, 及以上系统收到通知\(userInfo)")
+ urlString = userInfo["url"] as? String
+ if urlString != nil && (application.applicationState == .Active){
+ NSNotificationCenter.defaultCenter().postNotification(NSNotification(name: "NewVersion", object: urlString, userInfo: nil))
+ }
+ }//XCODE7 的环境下,消息的解析在这里实现。
+
+至此IOS的推送的集成基本完成了。但是要做到接收通知,打开通知栏就打开一个URL,还需要进一步的研究。(推送的消息中,content-alive字段必须为true否则将无法从服务器获取通知的内容)
+
+1, 当程序进程被杀死,通过通知栏启动程序(注意,如果收到通知,仍然通过ICON去启动程序,通知的内容是无法获取到的,必须通过通知才可以)
+func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
+ print("launchOptions ----",launchOptions)
+ if launchOptions != nil{
+ let remoteNoti = launchOptions![UIApplicationLaunchOptionsRemoteNotificationKey]
+ urlString = remoteNoti!["url"] as? String
+ }
+}//获取通知内容
+2, 当程序 处于后台,程序可以正常通过通知进入,并触发一个特定的操作
+
+3. 当程序处于前台
+ ios 10以下,是没有什么反应的,不弹出横幅,也无通知的声音。因此,可以通过添加这么一个判断来触发界面提示更新
+if urlString != nil && (application.applicationState == .Active){
+ NSNotificationCenter.defaultCenter().postNotification(NSNotification(name: "NewVersion", object: urlString, userInfo: nil))
+ }
+ IOS10 及以上则既可以弹出横幅又可以有声音,相关的逻辑可以在JPUSH的代理方法里去实现
+
+关于分组推送和精确推送
+极光推送里面的精准推送是通过idfa去实现的,但前提是app里面需要有明显的广告功能,如果没有的话,app将无法上架,再者,这个东西也不是完全的可靠,如果用户在设置里面停止广告跟踪的话,精准推送还是会失效的。
+思路:jpush中又一个registuserID这个id有个特点,就是程序如果被卸载,则重新生成一个新的来唯一表示设备,我们可以将用户ID作为key registuserID为value,如果重新安装,只需更新这个registuserID的值,即可唯一表示设备
+
+分组推送
+思路:先给用于一个别名alias,再给这个用户打上他所具备的标签,如 alias:liming, tag1:汽车 tag2:游戏 tag3:旅游
+ laias:jone tag1:美食 tag2:游戏 tag3:电影
+推送的时候,可以通过对tag的交并补等集合操作,实现对不同群体用户的信息的分类推送,如游戏这条推送,liming和jone都能收到