swift 消息推送

消息推送本身不难,基本分为远程推送(包含静默推送,特殊的远程推送)和本地推送;在实际项目中基本都会使用到,比较头痛的是接收到推送后的处理,以及app通过推送启动流程(最恶心的是iOS版本兼容再加上静默推送推送和远程推送的同时使用)。

  • iOS版本兼容,iOS10是一个节点(目前项目支持的最低版本9.3,所以必须要考虑到);

  • 静默推送和远程推送的同时使用,结合具体业务逻辑使用(静默推送主要用来app在前台时刷新状态,远程推送主要是做业务跳转)

iOS10注册推送需要设置代理来接受远程推送: UNUserNotificationCenter.current().delegate = self
顺便提下友盟推送注册的api:UMessage.registerForRemoteNotifications(launchOptions: launchOptions, entity: entity) { (granted, error) in }
参数:entity = UMessageRegisterEntity()launchOptions为app启动时的信息
回调:granted是否允许推送。

iOS10之前如果app在前台运行收到消息推送,是不会显示系统alert弹框,也有很多解决方案,但是我觉得比较好的是,使用本地推送,将收到的远程推送信息赋值给本地推送,然后app进入后台时发送本地推送。iOS10之后就没有这么麻烦了,但是呢,是否在前台运行需要显示推送弹框,还是需求说了算。

先看下iOS10之后的处理推送的方式,系统推送代理回调方法:

iOS10之后的代理回调

英文稍微好的都能看懂文档说的啥意思;
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void),这个方法是app在前台运行时,收到远程推送和静默推送(iOS10以后)的方法,其中 completionHandler回调参数是用来决定是否显示弹框声音和角标的,如:
completionHandler([.alert , .sound , .badge]),可以传空什么都不显示,但是不能不写这个回调,不然会有一个警告。

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
这个方法,是点击推送时,进入app调用的方法(不管app是否被杀死,只要点击推送时,都会调用这个方法,这个对于我们处理业务就有点稍微麻烦),还有最重要的一点是本地推送也是调用这个方法,他是通过参数去判断推送类型的,如:response.notification.request.trigger is UNPushNotificationTrigger-远程推送response.notification.request.trigger is UNLocationNotificationTrigger-本地推送,然并卵,这对于我们处理业务并没有什么实质性的帮助,但是,iOS10之前处理本地推送的回调方法是:
func application(_ application: UIApplication, didReceive notification: UILocalNotification),很无奈啊表示。
再看看iOS10之前收到远程推送的方法:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
顺便说一句这个也是所有静默推送会走的一个方法,那么iOS10之后app在前台收到静默推送时,会走二个方法?对的,所以处理静默推送时,需要注意下(但是大多数情况也没啥问题就是再刷新一次状态而已),先看回调,这个是告诉系统刷状态的,一般都是completionHandler (UIBackgroundFetchResult.newData),重点是处理消息推送!!,首先如果是iOS10以后,那么肯定是静默推送。重点是iOS10以前,可能是静默推送也就是远程推送(静默推送和远程推送需要和后台商量字段去区分的),还要根据app的状态去判断用户是否点击了推送(比较麻烦也比较恶心,也难怪iOS10之后会改掉)

swift 消息推送_第1张图片
在项目中根据需求的实际处理

我们区分静默推送和远程推送的字段是type。前台运行时(app状态为.active),目前需要显示alert,我用的是本地推送,实际上其他所有情况都应该是iOS10之前app点击推送被启动所调用的方法。我处理静默推送和远程推送用的是一个方法,大家不要误解,应该是不同的处理逻辑,只是我们项目中需求比较特殊,我用的一个方法,里面再去做的区分处理。

顺便再过一下app的启动(主要是点击推送),文中提到只要点击图送启动app都会调用推送方法,不过呢app被杀死时推送携带的信息还会存在于
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 的launchOptions中(launchOptions [UIApplication.LaunchOptionsKey.remoteNotification],launchOptions?[UIApplication.LaunchOptionsKey.localNotification])
如果app被杀死时,启动app大多数都会有广告页(广告业点击还会跳转,比较头痛的是广告是后台配置的可能会不存在,大多数广告页不带有导航控制器),我们需要在启动app时处理一些推送消息(主要是跳转指定界面),这就会导致二个问题:
1.如果在推送回调中处理,那么当存在广告页的时候,广告页不带导航控制器(present的就不考虑了)不能跳到指定的界面,那就在app启动的方法中处理,但是当不存在广告页的时候,推送消息会被处理二次,并有可能crash。
2.如果在推送回调中根据app状态处理,感觉好麻烦,怎么去准确的区分。

但是实际上呢,这些都是小问题。总有办法去解决(比如在处理推送时我会多二个参数,app是否为杀死时启动,app被杀死时启动时是否包含推送消息,来避免重复处理推送消息)。再比如:看了下其他app在点击推送时,好多app杀死启动时是不会显示广告页的直接从跟试图控制器push到指定界面(当然也有都显示的跳转到广告界面详情返回时,是推送指定界面,再返回才是首页)。

  • app只有在前台时,才能收到推送的消息的具体内容。app如果不在前台那么收到的推送信息包含在alert里面,点击alert会触发对应的回调方法(文中提到的)

  • 收到静默推送时,可以立刻拿到静默推送的具体内容,执行对应的处理方法,app只有在没有被杀死时才能收到静默推送。

  • 处理推送消息根据具体的业务需求去处理,不要重复处理推送消息。如果版本最低支持iOS10,那么处理起来很简单,二个代理回调(分别为前台收到,和后台或者杀死收到)基本解决所有问题,如果兼容iOS10之前的就有点麻烦(在同一个方法里处理),本地推送还是其他方法。

你可能感兴趣的:(swift 消息推送)