【问题标题】:iOS 8 enabled device not receiving PUSH notifications after code update代码更新后启用 iOS 8 的设备未收到推送通知
【发布时间】:2014-11-12 14:40:05
【问题描述】:

我最近将我的一部测试 iPhone 升级到了 iOS 8,然后升级了 PUSH 注册码 如下(使用 xCode 6)

-(BOOL)hasNotificationsEnabled {

    NSString *iOSversion = [[UIDevice currentDevice] systemVersion];
    NSString *prefix = [[iOSversion componentsSeparatedByString:@"."] firstObject];
    float versionVal = [prefix floatValue];


    if (versionVal >= 8)
    {

        NSLog(@"%@", [[UIApplication sharedApplication]  currentUserNotificationSettings]);
        //The output of this log shows that the app is registered for PUSH so should receive them

        if ([[UIApplication sharedApplication] currentUserNotificationSettings].types != UIUserNotificationTypeNone) {

            return YES;

        }

    }
    else
    {
        UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
        if (types != UIRemoteNotificationTypeNone){
            return YES;
        }

    }

    return NO;
}

-(void)registerForPUSHNotifications {

    NSString *iOSversion = [[UIDevice currentDevice] systemVersion];
    NSString *prefix = [[iOSversion componentsSeparatedByString:@"."] firstObject];
    float versionVal = [prefix floatValue];


    if (versionVal >= 8)
    {


            //for iOS8
        UIUserNotificationSettings *settings =
        [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |
         UIUserNotificationTypeBadge |
         UIUserNotificationTypeSound categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];


    }
    else
    {

            [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];


    }
}

尽管进行了此次升级,并且 [[UIApplication sharedApplication] currentUserNotificationSettings] 显示设备已启用 PUSH,但我没有收到 PUSH 通知。

我正在使用 Parse 并按照他们所关心的 (https://parse.com/tutorials/ios-push-notifications) 做所有事情。

有人遇到同样的问题吗?还有什么我可能会错过的吗?

【问题讨论】:

  • 查看用于注册推送通知的代码会很有帮助,因为 iOS 8 的 API 已更改。请参阅此处:stackoverflow.com/questions/24049266/…
  • 什么意思?代码在那里..
  • 哦,奇怪。我没有看到下面有更多代码。我的错。
  • 只要确保您没有将测试应用程序与生产服务器一起使用。在 iOS 开发 4 年后,我仍然陷入这个陷阱。
  • 这个链接对我有用..!stackoverflow.com/questions/4086599/…

标签: ios iphone notifications parse-platform push


【解决方案1】:

iOS 8 更改了注册推送通知的方式: 以下是 iOS 9 之前所有版本的代码:

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])
{
    [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];

}
else
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}

如果您想检查是否启用了推送通知,请使用以下代码:

- (BOOL) pushNotificationOnOrOff
{
    if ([UIApplication instancesRespondToSelector:@selector(isRegisteredForRemoteNotifications)]) {
        return ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]);
    } else {
        UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
        return (types & UIRemoteNotificationTypeAlert);
    }
}

#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

以上代码只能在 Xcode 6+ 上运行...

【讨论】:

  • 检查应该使用respondsToSelector,而不是操作系统版本。
  • 答案可能是错误的。在“其他”中,应该是 UIRemoteNotificationTypeXXXXX 而不是 UIUserNotificationType****。 UIUserNotificationType**** 在早期的 iO​​S 中没有定义,会导致应用崩溃。
  • 好吧@karim 其 100% 测试过的代码和它的工作很棒。我无法理解人们如何在不测试自己的情况下对答案投反对票。所以最好先测试,然后再对某人的答案投反对票。 .. 为了您的善意信息,我的应用程序已上线,推送通知也在 iOS 8 及之前的版本上运行。
  • 嗯,你知道 UIUserNotificationTypeBadge 等等都是 iOS 8.0 定义的。所以 xcode 5 会有编译器错误。但是,由于它是一个常数,它将在小于 8.0 的设备中运行时运行。最好使用旧常量,[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
  • 文档说你应该只在调用 didRegisterUserNotificationSettings 后调用 registerForRemoteNotifications
【解决方案2】:

.m 文件的顶部添加这一行

 #define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

1) 您必须在IOS8 注册推送通知时设置条件。 将此代码添加到应用程序did finish launch

if(IS_IOS_8_OR_LATER) {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes: (UIRemoteNotificationTypeBadge
                                                                                         |UIRemoteNotificationTypeSound
                                                                                       |UIRemoteNotificationTypeAlert) categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
 } else {
    //register to receive notifications
    UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
 }

2) 然后为IOS8添加这个方法

#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

然后您的通知委托方法将被调用。希望对你有帮助!!!

【讨论】:

  • 仅当您为一个操作系统版本分发时才使用此方法。如果您将基本版本设置为 7 并将分发目标设置为 8,这将在 iOS 7 上崩溃;如果您将分发目标设置为 7,它将无法在 8 上运行。正确的方法是运行时检查,如 penkaj 的回答(尽管目前使用错误的运行时检查,请参阅我的评论)。
  • 是的,你可以设置 if else 条件然后没问题。谢谢!!
  • 我编辑了代码,现在它也适用于 ios7,是的,您必须在 IOS8 下添加那些旧的远程通知委托方法,以便在任何推送到达时获取回调。
  • @Nits007ak,你在真机ios 7上测试过推送吗?
  • @tesmojones 是的,我测试它的工作正常......你需要添加远程通知的旧委托方法didRegisterForRemoteNotificationsWithDeviceToken,didReceiveRemoteNotification 低于IOS8
【解决方案3】:
The code below resolved:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
    UIUserNotificationType types;
    types = [[UIApplication sharedApplication] currentUserNotificationSettings].types;
    if (types & UIUserNotificationTypeAlert)
        pushEnabled=YES;
    else
        pushEnabled=NO;
}
else
{
    UIRemoteNotificationType types;
    types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
    if (types & UIRemoteNotificationTypeAlert)
       pushEnabled=YES;
    else
       pushEnabled=NO;

}

【讨论】:

  • types & UIUserNotificationTypeAlert 在 iOS8 上返回 false
【解决方案4】:

运行时和旧编译器安全选项...如果您在旧 xcode(5.0 或更早版本)中运行

    // changes of API in iOS 8.0
- (void) registerForPushNotification
{
    NSLog(@"registerForPushNotification");
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    {

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 //__IPHONE_8_0 is not defined in old xcode (==0). Then use 80000

        NSLog(@"registerForPushNotification: For iOS >= 8.0");

        [[UIApplication sharedApplication] registerUserNotificationSettings:
            [UIUserNotificationSettings settingsForTypes:
                (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
                                              categories:nil]];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
#endif
    } else {
        NSLog(@"registerForPushNotification: For iOS < 8.0");
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
    }
}

【讨论】:

    【解决方案5】:

    如果您同时拥有 iOS 8 和旧版本,请尝试以下操作:

    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
        // For iOS 8
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else {
        // For iOS < 8
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
    }
    

    来自 Apple 的开发网站:

    UIUserNotificationSettings

    一个 UIUserNotificationSettings 对象封装了 您的应用可以向用户显示的通知。应用程序 结合本地或推送使用可见或可听警报 通知必须注册他们使用的警报类型。 UIKit 将您提供的信息与用户的偏好相关联 确定您的应用可以使用哪些类型的警报。

    使用此类封装您的初始注册请求并查看请求结果。创建此类的实例并指定您的首选设置后,调用 UIApplication 类的registerUserNotificationSettings: 方法来注册这些设置。根据用户偏好检查您的请求后,应用程序将结果传递给其应用程序委托的 application:didRegisterUserNotificationSettings: 方法。传递给该方法的对象指定允许您的应用使用的通知类型。

    除了注册应用程序的警报类型外,您还可以使用此类注册自定义操作组以与本地或推送通知一起显示。自定义操作代表您的应用可以执行的即时任务以响应通知。您定义操作组并将整个组与给定通知相关联。当显示相应的警报时,系统会为您指定的每个操作添加按钮。当用户点击其中一项操作的按钮时,系统会唤醒您的应用并调用其应用委托的application:handleActionWithIdentifier:forRemoteNotification:completionHandler:application:handleActionWithIdentifier:forLocalNotification:completionHandler: 方法。使用这些方法来执行请求的操作。

    【讨论】:

      【解决方案6】:

      很简单:

      xcode6中的项目的didFinishLaunchingWithOptions中添加以下行

       [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
       [[UIApplication sharedApplication] registerForRemoteNotifications];
      

      【讨论】:

        【解决方案7】:
        if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
            // For iOS 8
        
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        
         [[UIApplication sharedApplication] registerForRemoteNotifications];
        } 
        
        else 
        {
            // For iOS < 8
            [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
             (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
        }
        

        之后:

        1. 从设备中删除不再有推送通知的应用。
        2. 完全关闭设备,然后重新打开。
        3. 转到设置并提前一天设置日期和时间
        4. 再次关闭设备并将其重新打开
        5. 再次安装应用程序,它会像您第一次安装它一样要求通知。
        6. 如果没有自动设置,请再次重置您的日期/时间。

        这将重置通知设置。重新安装应用程序,一切都会正常工作:)

        【讨论】:

        • 谢谢!我的通知提示有问题,这解决了它。
        【解决方案8】:

        我试图获取设置对象的类型信息,发现类型属性基本上是一个位掩码。以下是提取信息的方法。

        我的示例是在 Swift 中,但 >= iOS 8.0。

            let settings = UIApplication.sharedApplication().currentUserNotificationSettings()
        
            if settings.types.rawValue & UIUserNotificationType.Alert.rawValue == UIUserNotificationType.Alert.rawValue
            {
               // can receive alert!
            }
            else
            {
               // if the user is not even able to receive alerts, show him a hint on how to reenable notifications in system settings
            }
        
            if settings.types.rawValue & UIUserNotificationType.Badge.rawValue == UIUserNotificationType.Badge.rawValue
            {
                // can receive badge!
            }
            if settings.types.rawValue & UIUserNotificationType.Sound.rawValue == UIUserNotificationType.Sound.rawValue
            {
                // can receive sound!
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-01-03
          • 1970-01-01
          • 2015-02-09
          • 2020-02-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多