手把手教你在 SwiftUI 中实现推送通知。
第一步:请求推送权限
在 SwiftUI 中,我们需要先导入必要的框架,然后创建一个自定义的 AppDelegate。是的,即使是 SwiftUI,推送通知还是需要用到 AppDelegate(希望苹果以后能改进这点)。
import SwiftUI
import UserNotifications
// 自定义 AppDelegate
class CustomAppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
var app: YourApp?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// 注册远程通知
application.registerForRemoteNotifications()
// 设置通知代理
UNUserNotificationCenter.current().delegate = self
returntrue
}
}
然后在你的主 App 文件中集成这个 AppDelegate:
@main
struct YourApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: CustomAppDelegate
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
appDelegate.app = self
}
}
}
}
第二步:处理设备令牌
当用户同意接收推送后,苹果会给我们一个设备令牌。这就像是这台设备的"收货地址":
extension CustomAppDelegate {
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// 把设备令牌转换成字符串
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print("设备令牌:\(token)")
// TODO: 把这个令牌发送给你的服务器
}
func application(_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("注册失败:\(error)")
}
}
第三步:处理收到的通知
这里有两种情况需要处理:App 在前台时和 App 在后台时。
extension CustomAppDelegate: UNUserNotificationCenterDelegate {
// App 在前台时收到通知
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
// 即使 App 在前台也显示通知
return [.badge, .banner, .list, .sound]
}
// 用户点击通知时
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse) async {
print("用户点击了通知:\(response.notification.request.content.title)")
// 可以在这里处理深度链接
iflet pageLink = response.notification.request.content.userInfo["pageLink"] as? String {
// 导航到特定页面
}
}
}
第四步:在 ContentView 中请求权限
现在让我们在主界面添加一个按钮来请求推送权限:
struct ContentView: View {
@Stateprivatevar notificationEnabled = false
var body: some View {
VStack(spacing: 20) {
Text(notificationEnabled ? "推送已开启 ✅" : "推送未开启 ❌")
.font(.title2)
Button("开启推送通知") {
requestNotificationPermission()
}
.buttonStyle(.borderedProminent)
}
.padding()
}
func requestNotificationPermission() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
DispatchQueue.main.async {
self.notificationEnabled = granted
if granted {
// 用户同意了,注册远程通知
UIApplication.shared.registerForRemoteNotifications()
}
}
}
}
}
测试推送通知
开发阶段测试推送通知有几种方法:
1、创建测试文件(.apns)
创建一个 test.apns 文件:
{
"aps": {
"alert": {
"title": "测试通知",
"body": "这是一条测试消息 🎉"
},
"badge": 1,
"sound": "default"
},
"pageLink": "View2",
"Simulator Target Bundle": "你的Bundle ID"
}
然后直接拖到模拟器上就能看到通知了!
2、使用终端命令
xcrun simctl push booted 你的Bundle包名 test.apns
进阶技巧:深度链接
推送通知最强大的功能之一就是深度链接。你肯定有这种需求,比如点击推送后直接跳转到订单详情页,或者跳转到某个页面。
struct ContentView: View {
@Environment(CustomAppDelegate.self) privatevar appDelegate
@Stateprivatevar navigationPath: [String] = []
var body: some View {
@Bindablevar appDelegate = appDelegate
NavigationStack(path: $appDelegate.mainPageNavigationPath) {
List {
NavigationLink("订单列表", value: "orders")
NavigationLink("消息中心", value: "messages")
NavigationLink("个人中心", value: "profile")
}
.navigationTitle("推送通知示例")
.navigationDestination(for: String.self) { value in
DetailView(page: value)
}
}
}
}
从服务器发送推送
如果你用 Node.js 做后端,可以这样发送推送:
const apn = require('apn');
// 配置 APNs
const apnProvider = new apn.Provider({
token: {
key: 'path/to/APNsAuthKey.p8',
keyId: '你的KeyID',
teamId: '你的TeamID',
},
production: false// 开发环境
});
// 创建通知
const notification = new apn.Notification({
alert: '你有新订单啦!',
sound: 'default',
badge: 1,
payload: {
pageLink: 'orders'
}
});
// 发送
apnProvider.send(notification, deviceToken).then(result => {
console.log('发送成功:', result);
});
常见坑点和解决方案
1、模拟器 vs 真机
iOS 11.4 之后模拟器支持推送了,但功能还是有限。如果要测试所有功能,还是得用真机。
2、Safari 不支持 new Notification()
必须用服务工作者的 showNotification() 方法:
// ❌ 错误方式
new Notification("标题", options)
// ✅ 正确方式
await registration.showNotification("标题", options)
3、证书配置
这可能是最让人头疼的部分。记得在 Apple Developer 后台:
• 开启 Push Notifications 功能
• 创建 APNs 密钥(记得保存好,只能下载一次!)
• 在 Xcode 项目设置中启用推送通知
一些实用的第三方服务
如果你不想自己搭建推送服务器,也可以选择这些服务:
• Firebase Cloud Messaging (FCM):Google 的免费服务,功能强大
• OneSignal:有免费额度,支持 A/B 测试
• 极光推送:国内用得比较多,文档是中文的
推送通知虽然看起来步骤多,但其实每一步都很简单。关键是要理解整个流程,然后一步步实现就好了。
记住几个要点:
• 一定要处理用户拒绝权限的情况
• 不要滥用推送,用户会卸载你的 App 的
• 推送内容要有价值,别发"今天天气真好"这种废话
