为什么没有调用RegisterForRemoteNotificationsWithDeviceToken

时间:2010-11-03 11:31:46

标签: objective-c apple-push-notifications

我正在制作一个我希望实施Apple推送通知服务的应用程序。我按照this tutorial中给出的分步说明进行操作。

但是,这些方法仍未被调用。我不知道造成这个问题的原因。任何人都可以帮助我吗?

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
        //NSString * token = [[NSString alloc] initWithData:deviceTokenencoding:NSUTF8StringEncoding];
        NSString *str = [NSString stringWithFormat:@"Device Token=%@",deviceToken];
        NSLog(@"Device Token:%@",str);

        //NSLog(@"Device token is called");
        //const void *devTokenBytes = [deviceToken bytes];
        //NSLog(@"Device Token");
    }

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
        NSString *str = [NSString stringWithFormat: @"Error: %@", err];
        NSLog(@"Error:%@",str);    
    }

20 个答案:

答案 0 :(得分:69)

我遇到了同样的问题:调用registerForRemoteNotificationTypes:既未调用application:didRegisterForRemoteNotificationsWithDeviceToken:也未调用application:didFailToRegisterForRemoteNotificationsWithError:

我最终在Apple的技术说明TN2265的帮助下解决了这个问题。

这就是我所做的:

首先,我仔细检查了我确实是registering correctly for Push Notifications,包括验证我的“aps-environment”密钥的配置文件以及.app文件本身的代码签名。我把这一切都设置得正确。

然后我必须在控制台中调试推送通知状态消息(您需要在设备上安装PersistentConnectionLogging.mobileconfig配置文件并重新启动它。请参阅“观察推送状态消息”下的TN2265)。我注意到apns进程启动了一个计时器并计算了一个最小的开火日期,这让我怀疑APN正在通过推送通知注册确认消息,如TN2265所示:

  

重置iOS上的推送通知权限警报

     

第一次启用推送的应用注册推送通知时,iOS会询问用户是否希望接收该应用的通知。一旦用户响应此警报,除非设备已恢复或应用程序已卸载至少一天,否则不会再次显示该警报。

     

如果您想模拟首次运行的应用,可以将应用程序卸载一天。通过将系统时钟向前设置一天或更长时间,完全关闭设备,然后重新打开设备,您可以实现后者而无需实际等待一天。

因此,我从设备中删除了该应用,然后在“设置”中手动更改了iPhone的日期,重新启动了该设备,并重新安装了该应用。

下次我的代码调用registerForRemoteNotificationTypes时,它会按预期收到回调。

这解决了我的问题。希望能帮助到你。

答案 1 :(得分:66)

在iOS 8中,不推荐使用某些方法。按照以下步骤进行iOS 8兼容性

1。注册通知

if([[UIDevice currentDevice] systemVersion].floatValue >= 8.0)
{
    UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];    
}
else
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound|UIRemoteNotificationTypeBadge)];
}

2。添加新的2种方法

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    //register to receive notifications
    [application registerForRemoteNotifications];
}

//For interactive notification only
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
    else if ([identifier isEqualToString:@"answerAction"]){
    }
}

注意:除了didRegisterForRemoteNotificationsWithDeviceTokendidReceiveRemoteNotification之外,iOS 8还需要以上两种新方法。否则将不会调用委托方法。

请参阅:Remote Notification iOS 8

答案 2 :(得分:26)

iOS 8 中,除了以不同方式请求推送通知访问外,您还需要以不同方式注册。

请求访问:

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    // iOS 8
    UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
    // iOS 7 or iOS 6
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}

处理注册设备:

// New in iOS 8
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [application registerForRemoteNotifications];
}

// iOS 7 or iOS 6
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    // Send token to server
}

答案 3 :(得分:12)

确保拨打电话(根据支持的通知类型进行更新)

[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];

,配置文件已启用APNS。启用APNS后,您可能需要重新下载配置文件。如果您遇到麻烦并且出现错误,那么也许您应该创建一个Entitlements.plist并添加具有值“development”或“production”的密钥“aps-environment”,具体取决于构建的类型(通常这个键值对是包含在配置文件中,但有时Xcode会混淆它们。)

答案 4 :(得分:11)

请记住,模拟器中不支持远程通知。因此,如果您在模拟器中运行应用程序,则不会调用didRegisterForRemoteNotificationsWithDeviceToken

答案 5 :(得分:6)

如果在启用和配置Apple推送通知服务之前使用配置文件,则需要再次重新下载配置文件。

从Xcode Organizer和iPhone / iPad删除配置文件。 转到Settings -> General -> Profiles -> [Your provisioning] -> Remove

安装新下载的配置文件。然后从XCode清理并运行项目。 现在应该调用didRegisterForRemoteNotificationsWithDeviceToken

答案 6 :(得分:3)

我犯了一个错误,忽略了一个引导我的实施细节。我试图想象一下,并在应用程序入门过程中向用户询问推送通知,因此我将registerForRemoteNotificationTypesdidRegisterForRemoteNotificationsWithDeviceTokendidFailToRegisterForRemoteNotificationsWithError全部放在自定义UIView中。

FIX:didRegisterForRemoteNotificationsWithDeviceTokendidFailToRegisterForRemoteNotificationsWithError需要在UIApplicationDelegateYourAppDelegate.m)中触发。

现在看来很明显,嘿。

答案 7 :(得分:3)

确保您的互联网连接已开启。 由于互联网连接,我花了几个小时才收到工作通知。

答案 8 :(得分:3)

如果您已将推送添加到现有应用ID,请确保重新生成配置文件。如果您不这样做,该配置文件将不会知道您是否启用了推送应用程序ID。

答案 9 :(得分:3)

试试这个为我工作,

第一步

 UIApplication *application = [UIApplication sharedApplication];
 if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
                                                                                     |UIUserNotificationTypeSound
                                                                                     |UIUserNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
 } 
 else {
      UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
     }

在上面的方法中添加以下代码

 #ifdef __IPHONE_8_0
   - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
   {
  //register to receive notifications
  [application registerForRemoteNotifications];
  }

 - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
  {
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
   else if ([identifier isEqualToString:@"answerAction"]){
   }
}
 #endif

第二步

添加以下代码功能

 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 

您将在以下功能中获得设备令牌

$sql = "SELECT * FROM climbs 
                 WHERE userlogged = (SELECT user_id FROM users WHERE username = $user)
       ";

详情请参阅This

希望这对某些人有帮助。

答案 10 :(得分:2)

-​(BOOL)application:(UIApplication​*)application​ didFinishLaunchingWithOptions:(NSDictionary​*)launchOptions​{​​​​ ​​​​ ​​​​//​Override​point​for​customization​after​application​launch.
​​​​//​Add​the​view​controller’s​view​to​the​window​and​display. ​​​​[window​addSubview:viewController.view]; ​​​​[window​makeKeyAndVisible];
NSLog(@”Registering for push notifications...”);
 [[UIApplication sharedApplication]
registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound)]; 
​​​​return​YES;
}


- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
}
NSString *str = [NSString stringWithFormat:@”Device Token=%@”,deviceToken];
NSLog(@”%@”, str);


- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSString *str = [NSString stringWithFormat: @”Error: %@”, err]; NSLog(@”%@”, str);
}


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
}
for (id key in userInfo) { NSLog(@”key: %@, value: %@”, key, [userInfo objectForKey:key]);
}

答案 11 :(得分:2)

获取设备令牌的最低要求无需配置应用ID,配置或证书等,因此无需设置代码签名调用委托方法 didRegisterForRemoteNotificationsWithDeviceToken

我刚刚在Xcode 7中创建了一个新的iOS项目,用于默认设置的单视图,并提供了一个随机的bundle id,如com.mycompany.pushtest,它没有在apple dev portal中配置。

使用以下代码,我可以在iPad上的didRegisterForRemoteNotificationsWithDeviceToken方法中使用 Internet 访问WIFI获取我的设备令牌。我的设备已连接,我只是直接从xcode运行应用程序并在xcode的控制台中查看值。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   

{  
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])  
    {  
        UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound);  
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes categories:nil];  
        [application registerUserNotificationSettings:settings];  
        [application registerForRemoteNotifications];  
    }  
    else  
    {  
        // Register for Push Notifications, if running iOS version < 8  
        [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];  
    }  
    return YES;  
}  


- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Error: %@", error.description);
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken);
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    NSLog(@"NotificationSettings: %@", notificationSettings);
}

答案 12 :(得分:1)

我对此有一点意见。最近我也面临这个问题。我已经做了一切 根据文件,但委托方法没有调用。最后我看到了 一篇文章说网络问题。然后我改变了网络和 它工作正常。所以关心网络也因为很少有网络可以阻止 APNS。

答案 13 :(得分:1)

如果关闭app的推送消息,

永远不会调用appdidRegisterForRemoteNotificationsWithDeviceToken

答案 14 :(得分:1)

浪费了最烦人的3小时后,请按照以下步骤解决此问题:

  1. 删除应用

  2. 重置设备

  3. 再次运行

它奏效了

答案 15 :(得分:0)

这件事发生在我身上,因为我重置了&amp;删除了手机上的所有数据(想要开发电话使用)。再次设置手机后,这会阻止APN连接。

我尝试过各种各样的东西,但唯一能解决的问题就是将手机设置为与新SIM卡下的运营商合作。

此链接提供了有关可能发生的事情的更多提示:https://developer.apple.com/library/ios/technotes/tn2265/_index.html

它表示APN试图通过运营商/塔优先连接而不是wifi。也许这个问题也发生在wifi网络上阻塞端口5223的路由器上,但​​我对此表示怀疑,因为它在全局重置发生之前的前一天工作正常。

答案 16 :(得分:0)

对我来说,解决了它的目的是构建设置和代码签名部分,手动选择代码签名标识和配置文件。显然,自动设置没有找到正确的设置,因此应用程序没有得到适当的授权。

答案 17 :(得分:0)

另外,请勿忘记检查Apple https://developer.apple.com/system-status/的系统状态。

我尝试过上面发布的所有解决方案,但最终的错误是因为APNS服务已关闭!第二天所有人都按预期再次工作。

此外,您的回调方法中有一个拼写错误:

- (void)application:(UIApplication *)appdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

由于Rupesh指出正确的方法名称是:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

这可能就是你在案件中从未收到过令牌的原因!

答案 18 :(得分:0)

您需要从didFinishLaunchingWithOptions调用registerForNotifications方法。

 func registerForNotifications(){

        if #available(iOS 10.0, *) {

            let center = UNUserNotificationCenter.current()
            center.delegate = self
            center.requestAuthorization(options:[.alert,.sound,.badge]) { (granted, error) in
                if granted{
                    UIApplication.shared.registerForRemoteNotifications()
                }else{

                    print("Notification permission denied.")

                }
            }

        } else {

            // For iOS 9 and Below
            let type: UIUserNotificationType = [.alert,.sound,.badge];
            let setting = UIUserNotificationSettings(types: type, categories: nil);
            UIApplication.shared.registerUserNotificationSettings(setting);
            UIApplication.shared.registerForRemoteNotifications()
        }
    }

 func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        let token = String(format: "%@", deviceToken as CVarArg).trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "")
        print(token)

    }


extension AppDelegate : UNUserNotificationCenterDelegate{

    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter,  willPresent notification: UNNotification, withCompletionHandler   completionHandler: @escaping (_ options:   UNNotificationPresentationOptions) -> Void) {
        print("Handle push from foreground”)

        let info = ((notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
        if let type = info.value(forKey: "type") as? Int{
            if type == 0 {  

         // notification received ,Handle your notification here

            }
        }
    }

    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        print("Handle push from background or closed")

        let info = ((response.notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
        if let type = info.value(forKey: "type") as? Int{
            if type == 0 {   

            // notification received ,Handle your notification here
            }
        }
    }
}

答案 19 :(得分:0)

我有一个不同的问题,其中我的推送通知回调被第三方库劫持,我已经包含,即Firebase。这些库调用push通知回调方法来获取回调。

希望这有助于某人。