本文旨在对 iOS 推送进行一个完整的剖析,若是你以前对推送一无所知,那么在你认真地阅读了全文后必将变成一个推送老手,你将会对其中的各类细节和原理有充分的理解。如下是 pikacode 使用 iOS 推送的一些经验,欢迎互相交流,指出错漏之处。ios
推送服务能够说是全部 App 的标配,不管是哪一种类型的 App,推送都从很大程度上决定了 App 的 打开率、使用率、存活率 。所以,熟知并掌握推送原理及方法,对每个开发者来讲都是必备技能,对每个依赖 App 的公司来讲都相当重要。git
从 iOS 10 新增的 UserNotifications Framework
能够发现,Apple 整合了原有散乱的 API,而且增长了许多强大的功能。以 Apple 官方的角度来看,也必然是至关重视推送服务对 App 的影响、以及对 Apple iOS 生态圈长远发展的影响。github
badge
[如下简称角标] 等都会由系统来控制和展现)。在代码中注册推送服务:json
#ifdef __IPHONE_8_0
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge| UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
}
#else
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
#endif复制代码
若是注册成功,则能够在 AppDelegate.m
的以下方法中获取到 deviceToken
,它是对 该手机+该App 组合的一个惟一标识,当使用远程推送时,只需将推送消息发给指定的 deviceToken
便可使推送信息传达给指定手机的指定 App 上。所以若是你使用第三方,就须要在这个方法里将 deviceToken
传给第三方。(在 iOS 9 为了更好的保护用户隐私,会出现屡次重复删除/安装 App 致使 deviceToken
不断变化的状况。有时会出现一条推送手机会收到 2 次的问题,属于 iOS 9 系统问题)。服务器
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[JPUSHService registerDeviceToken:deviceToken];//将 deviceToken 传给极光推送
}复制代码
若是以上步骤均成功,此时你可以取到第三方提供的设备注册 id。可否取到该 id 值,能够做为判断设备是否可以成功推送的标准(见 Tip 6 - Registration ID)。由于当你取到该值时必然:微信
deviceToken
(APNs 能识别你的设备了)。deviceToken
传给第三方,成功在第三方生成了惟一标识注册 id(第三方能将你的设备信息传给 APNs 了)。didReceiveRemoteNotification
Remote Notification
,系统将推送传到 didReceiveRemoteNotification:fetchCompletionHandler:
(见 Tip 5 - 后台推送),不然此时代码中收不到推送。didFinishLaunchingWithOptions
。远程推送通知,分为 普通推送/后台推送/静默推送 3 种类型。存在延迟问题(因为 Tip 1 第 2 点,APNs 的不稳定及高峰时段的巨量请求所致)。app
普通推送性能
didReceiveRemoteNotification
(iOS 7 before)didReceiveRemoteNotification:fetchCompletionHandler:
(iOS 7 after)获取通知内容(前台展现横幅的方法看这里)。didFinishLaunchingWithOptions
获取通知内容。通知内容相似以下:fetch
{
"_j_msgid" = 200806057; // 第三方附带的 id,用于统计点击
aps = {
alert = "显示内容";
badge = 1; // App 角标,可推送 n、+n、-n 来实现角标的固定、增长、减小
sound = default; // 推送声音,默认系统三全音,如需使用本身的声音,须要将声音文件拖拽&拷贝至 Xcode 工程目录任意位置,并在推送时指定其文件名
};
key1 = value1; // 自定义字段,可设置多组,用于处理内部逻辑
key2 = value2;
}复制代码
后台推送ui
"content-available" = 1;
alert
、badge
、sound
中 至少 1 个字段
。didReceiveRemoteNotification
(iOS 7 before)didReceiveRemoteNotification:fetchCompletionHandler:
(iOS 7 after) 获取通知内容。didReceiveRemoteNotification:fetchCompletion Handler:
获取通知内容 // 获取状况中与普通推送的惟一不一样点,此时 iOS 系统容许开发者在 App 处于后台的状况下,执行一些代码,大概提供几分钟的时间,能够用来偷偷的刷新 UI、切换页面、下载更新包等等操做。didFinishLaunchingWithOptions
获取通知内容。通知内容相似以下:
{
"_j_msgid" = 2090737306;
aps = {
alert = "显示内容";
badge = 1;
"content-available" = 1; // 必带字段
sound = default;
};
key1 = value1;
}复制代码
静默推送
"content-available" = 1;
,所以静默必然是后台的。alert
、badge
、sound
。didReceiveRemoteNotification
(iOS 7 before)didReceiveRemoteNotification:fetchCompletionHandler:
(iOS 7 after) 获取通知内容。didReceiveRemoteNotification:fetchCompletion Handler:
获取通知内容 //获取状况中与普通推送的惟一不一样点,此时 iOS 系统容许开发者在 App 处于后台的状况下,执行一些代码,大概提供几分钟的时间,能够用来偷偷的刷新 UI、切换页面、下载更新包等等操做。{
"_j_msgid" = 3938587719;
aps = {
alert = "";
"content-available" = 1; // 必带字段
};
key1 = value1;
}复制代码
别名、标签、Registration ID 均是第三方提供的用于更方便地指定推送目标的功能。
NSUserDefaults
,本次剔除不须要的 tag 后,再从新设置。deviceToken
提供给第三方以后,其服务器会自动生成的指向该手机的惟一 id。通知 | 消息 | |
---|---|---|
送达时间 | 可能存在几秒延迟 | 几乎无延迟 |
获取时机 | 处于前台或后台能获取内容 | 仅处于前台能获取内容 |
离线内容 | 保留『一段时间』,过时会抛弃,没法查询历史内容 | 始终保留,可查询所有历史内容 |
系统展现 | 会展现(静默推送或App处于前台不展现) | 不展现 |