iOS推送注册后device token未在NSLog打印,如何修改代码实现正常打印?
解决方案
你当前的代码存在两个核心问题导致回调不触发:
- 调用
registerForRemoteNotifications的时机错误:你在注册通知配置后立刻调用了远程推送注册,此时用户还未完成授权弹窗的选择,只有用户同意授权后调用注册接口才会触发回调 - 未适配iOS10及以上系统的推送接口:旧的
registerUserNotificationSettings接口在iOS10后已经废弃,新版系统需要使用UserNotifications框架的新接口实现注册
第一步:导入依赖并添加代理
在AppDelegate.m文件头部导入UserNotifications框架,同时在类扩展中遵守UNUserNotificationCenterDelegate协议:
#import <UserNotifications/UserNotifications.h> @interface AppDelegate () <UNUserNotificationCenterDelegate> @end
第二步:修改注册逻辑
将didFinishLaunchingWithOptions中的推送注册逻辑替换为以下适配多版本的代码,把远程注册动作放到授权成功的回调中:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { // 适配iOS10+推送接口 if (@available(iOS 10.0, *)) { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted) { // 授权成功后再注册远程推送,切回主线程调用避免异常 dispatch_async(dispatch_get_main_queue(), ^{ [application registerForRemoteNotifications]; }); } else if (error) { NSLog(@"推送授权失败: %@", error); } }]; } else if (@available(iOS 8.0, *)) { // iOS8-iOS9系统适配 [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]]; } else { // iOS8以下系统适配 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; } // 原有启动推送处理逻辑保留 if (launchOptions != nil) { NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (dictionary != nil) { NSLog(@"Launched from push notification: %@", dictionary); } } return YES; } // 适配iOS8-iOS9的授权回调,用户选择后再注册远程推送 - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_DEPRECATED_IOS(8_0, 10_0) { if (notificationSettings.types != UIUserNotificationTypeNone) { [application registerForRemoteNotifications]; } } // 原有token回调和失败回调保留即可 - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { NSLog(@"My token is: %@", deviceToken); // 如果需要转成无特殊字符的字符串可以用以下代码 // NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; // token = [token stringByReplacingOccurrencesOfString:@" " withString:@""]; // NSLog(@"格式化后的token: %@", token); } - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { NSLog(@"Failed to get token, error: %@", error); }
必要排查项
修改代码后如果还是没有回调,请检查以下配置:
- 必须使用真机测试,模拟器无法获取device token
- 工程的
Signing & Capabilities标签页中必须添加Push Notifications能力 - 你使用的开发者证书必须已经开启推送服务权限
- 授权弹窗弹出后必须点击「允许」,如果之前点击过拒绝,需要到系统设置-对应App-通知中手动开启允许通知权限
内容的提问来源于stack exchange,提问作者programcode
相关产品推荐
相关产品推荐

