关于iOS推送的总结

本文目的

本文不讲证书配置,不讲APNS的原理,仅描述开发过程中遇到的坑坑洼洼。

推送中的一些坑

大家都知道iOS中推送有本地推送和远程推送。那么我们就分开说了,先说远程推送。

远程推送中的一些坑

就远程推送而言,应用推送到达的场景有:

  • App未启动
  • APP在后台
  • 用户正在玩App
    每种情况下有不同的处理方式,再加上不同的版本iOSApi不一致,导致处理逻辑相当繁琐。
    先介绍远程推送的一些代理方法

推送提醒方式

无论是远程推送还是本地推送,推送的提醒方式是由系统版本决定的,在设置—>悟空遥控器->通知里面可以选择推送的提醒方式。

远程推送

注册推送

方法一:

1
2
3
4
5
6
7
8
9
10
//iOS3到iOS8 有效,其中type的值如下枚举
- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types;
//iOS3到iOS8 有效
typedef NS_OPTIONS(NSUInteger, UIRemoteNotificationType) {
UIRemoteNotificationTypeNone = 0,
UIRemoteNotificationTypeBadge = 1 << 0,
UIRemoteNotificationTypeSound = 1 << 1,
UIRemoteNotificationTypeAlert = 1 << 2,
UIRemoteNotificationTypeNewsstandContentAvailability = 1 << 3,
}

方法二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//iOS8 之后有效, 调用该方法注册推送,必须先调用registerUserNotificationSettings设置推送形式。
- (void)registerForRemoteNotifications;
//UIUserNotificationSettings, UIUserNotificationType 取下面两个枚举值
+ (instancetype)settingsForTypes:(UIUserNotificationType)types
categories:(nullable NSSet<UIUserNotificationCategory *> *)categories;
// iOS8 到 iOS10
typedef NS_OPTIONS(NSUInteger, UIUserNotificationType) {
UIUserNotificationTypeNone = 0,
UIUserNotificationTypeBadge = 1 << 0,
UIUserNotificationTypeSound = 1 << 1,
UIUserNotificationTypeAlert = 1 << 2,
}
iOS 10+
typedef NS_OPTIONS(NSUInteger, UNAuthorizationOptions) {
UNAuthorizationOptionBadge = (1 << 0),
UNAuthorizationOptionSound = (1 << 1),
UNAuthorizationOptionAlert = (1 << 2),
UNAuthorizationOptionCarPlay = (1 << 3),
}

方法三:

1
2
3
//UNUserNotificationCenter 的方法 iOS 10+
- (void)requestAuthorizationWithOptions:(UNAuthorizationOptions)options
completionHandler:(void (^)(BOOL granted, NSError *error))completionHandler;

接收方法

1
2
3
4
5
// 如果APP正在运行时接收到远程推送消息,系统会调用此方法。iOS3-iOS10
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;
//程序处于后台或者被杀死状态,收到远程通知后,当你进入(aunch)程序时,系统调用此方法,iOS 7 之后
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;

如果两个代理方法都被实现了,系统将只调用application:didReceiveRemoteNotification:fetchCompletionHandler:

另外需要注意:从didFinishLaunchingWithOptions 方法里面可以获得APP从通知栏里启动并获取携带的推送参数,这里可以不做判断,都归于didReceiveRemoteNotification:fetchCompletionHandler 中处理。并且iOS10之后废弃了UIApplicationLaunchOptionsRemoteNotificationKey。

1
2
3
4
5
// iOS 10+ 后台推送消息接收
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler;
// iOS 10+ 前台推送消息处理, 可在APP 前台状态下,弹出推送弹窗
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(nonnull UNNotification *)notification withCompletionHandler:(nonnull void (^)(UNNotificationPresentationOptions))completionHandler;

取消推送

iOS10之前不能取消一个已发送未点击的本地通知,但是iOS10之后可以根据identifiers取消某一个指定的通知,不管是待发送的还是已发送未点击的。

1
2
3
4
5
6
7
8
9
10
11
12
//ios4-ios10 取消一个指定的推送
- (void)cancelLocalNotification:(UILocalNotification *)notification;
//ios4-ios10 取消所有的本地推送
- (void)cancelAllLocalNotifications ;
//iOS10 + 取消待推送的消息,根据identifiers
- (void)removePendingNotificationRequestsWithIdentifiers:(NSArray<NSString *> *)identifiers;
- (void)removeAllPendingNotificationRequests;
//iOS10 + 取消已经推送的消息,根据identifiers
- (void)removeDeliveredNotificationsWithIdentifiers:(NSArray<NSString *> *)identifiers __TVOS_PROHIBITED;
- (void)removeAllDeliveredNotifications __TVOS_PROHIBITED;

参考

http://www.simpleapples.com/2014/09/ios8-register-notification-fail/