跳到主要内容

设计推送系统

问题

如何设计 iOS 端的推送系统?

答案

架构

客户端设计

class PushManager {
// Token 管理
func didRegisterToken(_ token: Data) {
let tokenString = token.map { String(format: "%02.2hhx", $0) }.joined()
// 上报服务端,关联 userId
API.registerPushToken(token: tokenString, platform: "ios")
}

// 消息路由
func handleNotification(userInfo: [AnyHashable: Any]) {
guard let type = userInfo["type"] as? String else { return }
switch type {
case "chat":
Router.shared.navigate(to: "myapp://chat?id=\(userInfo["chatId"] ?? "")")
case "order":
Router.shared.navigate(to: "myapp://order?id=\(userInfo["orderId"] ?? "")")
default:
break
}
}
}

// Notification Service Extension - 富文本推送
class NotificationService: UNNotificationServiceExtension {
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
guard let content = request.content.mutableCopy() as? UNMutableNotificationContent,
let imageURL = content.userInfo["image"] as? String,
let url = URL(string: imageURL) else { return }

// 下载图片附件
URLSession.shared.downloadTask(with: url) { localURL, _, _ in
if let localURL,
let attachment = try? UNNotificationAttachment(identifier: "image", url: localURL) {
content.attachments = [attachment]
}
contentHandler(content)
}.resume()
}
}

常见面试问题

Q1: 推送到达率低怎么优化?

答案:APNs 不保证 100% 到达。可以补充长连接通道(WebSocket),App 前台时走长连接,后台走 APNs。同时维护推送回执,排查未达消息。

相关链接