如何在Kotlin Multiplatform中正确调用AppDelegate获取APNs设备令牌
在Compose Multiplatform中实现iOS APNs令牌获取并关联AppDelegate
问题场景
你使用Compose Multiplatform开发移动应用,需要在iOS端获取APNs令牌并提交到服务器。目前已编写Kotlin版AppDelegate和注册远程通知的代码,但AppDelegate的回调未触发,同时需要将NSData类型的设备令牌转换为标准十六进制字符串。
解决步骤
1. 关联SwiftUI App入口与自定义AppDelegate
由于你用SwiftUI的@main App结构体作为iOS入口,默认不会自动加载自定义AppDelegate,需通过UIApplicationDelegateAdaptor关联两者。修改iOS端Swift代码:
@main struct iOSApp: App { // 关联自定义AppDelegate @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate init() { HelperKt.doInitKoin() } var body: some Scene { WindowGroup { ContentView() } } }
2. 修正Kotlin AppDelegate的令牌解析与回调逻辑
将回调参数类型改为Data(对应Swift的Data),按Swift逻辑转换为十六进制字符串,并通过全局回调传递给业务层:
// 全局回调变量,用于接收令牌并传递给业务层 var notifyTokenCallback: ((String) -> Unit)? = null class AppDelegate : UIResponder(), UIApplicationDelegateProtocol { override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean { // 启动时请求通知权限,需用户授权才能获取令牌 UNUserNotificationCenter.current().requestAuthorization( UNAuthorizationOptions.Alert or UNAuthorizationOptions.Badge or UNAuthorizationOptions.Sound ) { granted, error -> if (granted) { application.registerForRemoteNotifications() } } return true } override fun application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken: Data ) { // 把Data转换为标准十六进制字符串,和Swift逻辑一致 val token = didRegisterForRemoteNotificationsWithDeviceToken.map { String.format("%02.2hhx", it) }.joinToString("") // 触发回调传递令牌 notifyTokenCallback?.invoke(token) println("APNs Token: $token") } override fun application( application: UIApplication, didFailToRegisterForRemoteNotificationsWithError: NSError ) { println("APNs注册失败: ${didFailToRegisterForRemoteNotificationsWithError.localizedDescription}") } companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta }
3. 完善Kotlin层的令牌获取逻辑
修改fetchNotifyToken函数,将业务层回调绑定到全局变量,确保AppDelegate能触发它:
actual fun fetchNotifyToken(tokenFun: (String) -> Unit) { // 保存业务层回调 notifyTokenCallback = tokenFun // 注册远程通知(若AppDelegate启动时未注册) UIApplication.sharedApplication.registerForRemoteNotifications() }
注:移除
suspend修饰符,因为registerForRemoteNotifications是异步操作,无需挂起函数。若业务层需协程处理,可在回调内切换到协程上下文。
4. 测试验证
运行iOS应用后,授权通知权限,控制台会打印APNs令牌,同时业务层回调会接收到该令牌,可在回调中完成令牌提交服务器的逻辑。
内容的提问来源于stack exchange,提问作者Mac Z
相关产品推荐
相关产品推荐

