iOS推送完整链路:数据从哪来,到哪去,怎么流
2026/8/22 12:54:02 网站建设 项目流程

上篇讲了挂起态存储,有读者说"链路那张图一带而过,想看清楚每个环节到底传了什么、数据往哪流"。这篇就专门干这一件事:把整条链路拆成一个个节点,标清楚每一段传的是什么数据、朝哪个方向流。

先认清链路上的四个"角色"

整条推送链,从头到尾只有四方参与。先把这四方认清楚,谁是谁、各自管什么:

┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 你的App │ │ 你的服务器 │ │ APNs │ │ iPhone系统 │ │ (Provider前端)│ │ (Provider后端)│ │ (苹果推送网关)│ │ + 你的App │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
角色大白话职责
你的App收信的那家申请收推送、上报门牌号、最终展示/处理消息
你的服务器寄信的人保管门牌号、决定推什么、把信交给邮局
APNs苹果总邮局唯一的推送网关,所有推送都从这过
iPhone系统小区收发室维护那唯一一条连接,接信、投递、代管

关键认知:这四方之间,数据不是单向一路走到底的,而是分成两个大阶段,方向还相反。

整条链路分两个阶段(方向相反)

很多人搞不清楚,就是因为把两个阶段混在一起看了。其实要分开:

阶段一【注册阶段】:数据从设备流向你的服务器(自下而上) 目的:让你的服务器拿到"门牌号"(device token) 阶段二【推送阶段】:数据从你的服务器流回设备(自上而下) 目的:把消息投递到设备上

必须先有阶段一,才可能有阶段二。没拿到门牌号,你服务器根本不知道往哪推。下面分别把两个阶段的数据流画清楚。

阶段一:注册(拿门牌号)——数据自下而上流

这个阶段的目标只有一个:你的服务器最终要拿到一个 device token(门牌号)。数据从App出发,绕一圈,最后落到你的服务器。

① 我想收推送 ┌─────────┐ ──────────────────────────> ┌─────────┐ │ 你的App │ │iPhone系统│ │ │ <────────────────────────── │ │ └─────────┘ ② 用户点了"同意" └─────────┘ │ │ │ │ ③ 去苹果注册 │ │ 这台设备+这个App │ ▼ │ ┌─────────┐ │ │ APNs │ │ │(苹果邮局) │ │ ④ 生成门牌号(token) └─────────┘ │ 发回给系统 │ │ <───────────────────────────────────────┘ │ ⑤ 系统把token交给App │ │ ⑥ App把token上报给自己的服务器 ▼ ┌─────────┐ │ 你的服务器 │ ← token最终存在这里!(存进数据库) └─────────┘

逐段说明数据流向和内容:

步骤数据从 → 到传的是什么
App → 系统“我想收推送”(申请权限)
系统 → 用户 → App弹窗,用户点"同意"
系统 → APNs“这台设备+这个App要注册”
④⑤APNs → 系统 → Appdevice token(门牌号)
App → 你的服务器把token上报,服务器存起来

对应代码,看数据在哪几个点落地:

// 【步骤①】App向系统申请UNUserNotificationCenter.current().requestAuthorization(options:[.alert,.badge,.sound]){同意了,_inif同意了{// 用户同意 → 触发系统去APNs注册(步骤③)UIApplication.shared.registerForRemoteNotifications()}}// 【步骤④⑤】APNs生成token,系统通过这个回调交给Appfuncapplication(_application:UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken:Data){// 这里第一次拿到门牌号lettoken=deviceToken.map{String(format:"%02x",$0)}.joined()// 【步骤⑥】关键!把门牌号上报给【你自己的服务器】// 数据流的终点在这:token存进你的数据库上报token给自己服务器(token)}

阶段一的核心结论:

数据流向:App → 系统 → APNs → 系统 → App → 你的服务器 最终落点:device token 存在【你的服务器数据库】里 这个token = "设备+App"的唯一门牌号 以后你想推送,就靠它找到这台设备

阶段二:推送(投递消息)——数据自上而下流

拿到门牌号后,才能推。这个阶段方向反过来了:数据从你的服务器出发,经过苹果邮局,投到设备上。

┌─────────┐ │ 你的服务器 │ ① 组装消息:内容 + 门牌号(token) └─────────┘ │ │ ② 建立连接,把消息交给苹果邮局 │ (用之前存的token指明投给谁) ▼ ┌─────────┐ │ APNs │ ③ 苹果验证:token合法吗?App还装着吗? │(苹果邮局) │ 通过 → 投递 / 不通过 → 丢弃并反馈 └─────────┘ │ │ ④ 通过那唯一一条长连接,投到设备 ▼ ┌─────────┐ │iPhone系统│ ⑤ 根据App当前状态,决定怎么处理 └─────────┘ │ │ ⑥ 交给App(或系统代为展示) ▼ ┌─────────┐ │ 你的App │ ← 消息最终到达 └─────────┘

逐段说明:

步骤数据从 → 到传的是什么
你的服务器内部组装 payload(消息内容)+ 取出目标token
你的服务器 → APNspayload + token,用HTTP/2连接发出
APNs内部校验token有效性
APNs → 系统走那条唯一长连接,投到设备
⑤⑥系统 → App按App状态处理(下面细讲)

你服务器发给APNs的数据长这样(payload):

{"aps":{"alert":{"title":"你有一条新消息","body":"点击查看详情"},"badge":1,"sound":"default"},"自定义字段":"跳转到订单页"}

发的时候,token放在请求路径里,指明投给哪台设备

POST https://api.push.apple.com/3/device/{这里放device_token} Body: 上面那段payload

阶段二的最后一段:进了系统后,数据往哪流取决于App状态

这是整条链路最容易忽略、也最关键的一段。消息到了iPhone系统(步骤⑤),接下来数据流向哪里,完全看你的App此刻是什么状态。

消息到达 iPhone系统 │ ├─ App在前台? │ → 系统直接把数据交给App的回调 │ 数据流:系统 → App(willPresent回调) │ ├─ App在后台/挂起(普通推送)? │ → 系统自己存进【通知数据库】,显示在通知栏 │ 数据暂时【不流向App】,App还在睡 │ 等用户点击 → 才流向App(didReceive回调) │ └─ App挂起(静默推送 content-available)? → 系统短暂唤醒App 数据流:系统 → App(didReceiveRemoteNotification回调)

三种情况的数据落点,对应三个不同的回调:

// 情况1:App在前台时,消息数据流到这里funcuserNotificationCenter(_center:UNUserNotificationCenter,willPresent notification:UNNotification,...){// 数据直接到达,App醒着,立即能处理let数据=notification.request.content.userInfo}// 情况2:App在后台/挂起,用户【点击通知】后,数据流到这里funcuserNotificationCenter(_center:UNUserNotificationCenter,didReceive response:UNNotificationResponse,...){// 消息之前一直躺在【系统通知数据库】里// 用户点击 → 系统唤醒App → 现在才把数据交还let数据=response.notification.request.content.userInfo}// 情况3:静默推送,App被短暂唤醒,数据流到这里funcapplication(_application:UIApplication,didReceiveRemoteNotification userInfo:[AnyHashable:Any],...){// App被摇醒几秒,数据直接到达,趁机处理let数据=userInfo}

这就是上篇"挂起态存储"的链路视角:普通推送在挂起时,数据流没有到达App,而是停在了系统的通知数据库里,等用户点击才继续往App流。

完整链路:一张图从头到尾

把两个阶段拼起来,标清所有数据流向:

═══════════ 阶段一:注册(拿门牌号,自下而上)═══════════ App ─①想收推送─> 系统 ─③注册─> APNs │ ④生成token │ App <─⑤交还token─ 系统 <──────────┘ │ └─⑥上报─> 你的服务器 【token存这里】 ═══════════ 阶段二:推送(投消息,自上而下)═══════════ 你的服务器 【取出token+组装消息】 │ │ ②发送(payload + token) ▼ APNs ③校验token │ │ ④走唯一长连接投递 ▼ iPhone系统 ⑤按App状态分流 │ ├─前台──> App(willPresent回调) ├─挂起(普通)──> 系统通知库暂存 ──用户点击──> App(didReceive回调) └─挂起(静默)──> 唤醒 ──> App(didReceiveRemoteNotification回调)

数据流的三个关键点,记住就不乱了

1. token的流向是"绕一圈回到你手里"

token从APNs生成 → 经系统 → 给App → App上报 → 存到你的服务器

很多人卡在这:token不是苹果直接给你服务器的,是先到App,App再交给你服务器。你服务器和APNs之间,注册阶段没有直接往来。

2. 推送阶段,你服务器和App之间【没有直接连接】

你的服务器 ✗直接✗ 你的App 你的服务器 → APNs → 系统 → App (必须绕苹果邮局)

你永远不能直接把消息推给App,必须经过APNs这个唯一网关。这是苹果的强制规定,也是为啥推送这么省电(全设备就一条连接)。

3. 最后一段的数据流向,是"条件分支",不是直线

到了系统这,数据不一定马上流到App 前台→直达App / 挂起普通→先停系统库 / 挂起静默→唤醒后达App

理解这一点,就理解了为啥"App睡着还能收推送"——因为最后那段数据流,系统能替App接管

用一句话概括整条链路的数据流动

注册时,门牌号(token)从设备一路上报、最终存进你的服务器;推送时,消息从你的服务器出发,必经苹果邮局(APNs),投到系统,再由系统按App状态决定是直接交给App、还是先替它代管。

两个阶段、方向相反、APNs是唯一枢纽——抓住这三点,整条链路的数据流动就彻底清楚了。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询