集成Push Kit无法获取pushCredentials token,求技术解决方案
Hey there! Let's break down why you're not receiving the VoIP push token and fix it step by step. From looking at your code, there are a few key issues and missing steps that are likely causing this problem:
1. Critical: PKPushRegistry is a Local Variable (Gets Destroyed Immediately)
In your didRegisterUserNotificationSettings method, you're creating voipRegistry as a local variable. As soon as this method finishes executing, the registry instance is deallocated from memory—so its delegate methods (like didUpdate pushCredentials) will never get called.
Fix: Declare voipRegistry as a property in your AppDelegate to keep it alive for the app's lifecycle:
class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? // Add this property private var voipRegistry: PKPushRegistry? // Rest of your code... }
2. Outdated Notification Permission API (iOS 10+ Compatibility)
You're using UIUserNotificationSettings, which is deprecated in iOS 10. For modern iOS versions, you need to use UNUserNotificationCenter to request notification permissions, which is required for Push Kit to work properly.
3. Missing Project Configuration Steps
Before diving into code fixes, make sure these project settings are correct:
- Go to your project's Capabilities tab:
- Enable Push Notifications.
- Enable Background Modes and check the Voice over IP option.
- Verify your App ID in Apple Developer Portal has Push Notifications (and VoIP service) enabled, and your Provisioning Profile includes these permissions.
- Always test on a real iOS device—simulators don't support VoIP push tokens.
Modified Working Code Example
Here's how to update your AppDelegate to fix these issues:
import UIKit import PushKit import UserNotifications // For iOS 10+ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? private var voipRegistry: PKPushRegistry? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { requestNotificationPermissions() return true } private func requestNotificationPermissions() { if #available(iOS 10.0, *) { let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .badge, .sound]) { [weak self] granted, error in guard granted, error == nil else { return } DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() self?.setupVoIPRegistry() } } } else { let notificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) UIApplication.shared.registerUserNotificationSettings(notificationSettings) } } // For iOS 9 and below func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { if notificationSettings.types != [] { application.registerForRemoteNotifications() setupVoIPRegistry() } } private func setupVoIPRegistry() { voipRegistry = PKPushRegistry(queue: DispatchQueue.main) voipRegistry?.desiredPushTypes = [.voIP] voipRegistry?.delegate = self print("VoIP registry initialized successfully") } } extension AppDelegate: PKPushRegistryDelegate { func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { let token = pushCredentials.token.map { String(format: "%02x", $0) }.joined() print("Received VoIP token: \(token)") // Print formatted token for easier use } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) { let payloadDict = payload.dictionaryPayload["aps"] as? [String: Any] let message = payloadDict?["alert"] as? String if UIApplication.shared.applicationState == .background { let localNotification = UILocalNotification() localNotification.alertBody = message localNotification.applicationIconBadgeNumber = 1 localNotification.soundName = UILocalNotificationDefaultSoundName UIApplication.shared.presentLocalNotificationNow(localNotification) } else { print("Received VoIP message: \(message ?? "No message")") } NSLog("Incoming VoIP notification payload: \(payload.dictionaryPayload)") } func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { NSLog("VoIP token invalidated") } } extension UIApplicationState { var stringValue: String { switch self { case .active: return "Active" case .inactive: return "Inactive" case .background: return "Background" @unknown default: return "Unknown" } } }
Final Checks
- After updating the code, clean your project (
Cmd+Shift+K) and rebuild. - Make sure your device is running a supported iOS version (Push Kit requires iOS 8+).
- Verify that you've accepted the notification permission prompt when launching the app.
内容的提问来源于stack exchange,提问作者Pradumna Patil

