registerForRemoteNotificationTypes: is not support

2020-01-27 08:55发布

When trying to register for push notifications under iOS 8.x:

application.registerForRemoteNotificationTypes(UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound)

I get the following error:

registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later.

Any ideas what is the new way of doing it? It does work when I run this Swift app on iOS 7.x.

EDIT

On iOS 7.x when I include the conditional code I get (either SystemVersion conditional or #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)

dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings

15条回答
再贱就再见
2楼-- · 2020-01-27 09:39

You can use this

if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) 
    {
        // for iOS 8
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];

        [application registerForRemoteNotifications];
    }
    else
    {
        // for iOS < 8
        [application registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
    }

    // RESET THE BADGE COUNT 
    application.applicationIconBadgeNumber = 0;
查看更多
Bombasti
3楼-- · 2020-01-27 09:41

for iOS 8 and above

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
查看更多
Emotional °昔
4楼-- · 2020-01-27 09:43

For iOS<10

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    //-- Set Notification
    if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) 
    {
           // iOS 8 Notifications
           [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];

           [application registerForRemoteNotifications];
    }
    else
    {
          // iOS < 8 Notifications
          [application registerForRemoteNotificationTypes:
                     (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
    }

     //--- your custom code
     return YES;
}

For iOS10

https://stackoverflow.com/a/39383027/3560390

查看更多
Emotional °昔
5楼-- · 2020-01-27 09:43

I couldn't figure out what the "categories" NSSet variable should be set to, so if someone could fill me in I will gladly edit this post. The following does, however, bring up the push notification dialog.

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

Edit: I got a push notification to send to my phone with this code, so I'm not sure the categories parameter is necessary.

查看更多
我只想做你的唯一
6楼-- · 2020-01-27 09:43

So it turns out that because AnyObject is the spiritual successor to id, you can call any message you want on AnyObject. That's the equivalent of sending a message to id. Ok, fair enough. But now we add in the concept that all methods are optional on AnyObject, and we have something we can work with.

Given the above, I was hopeful I could just cast UIApplication.sharedApplication() to AnyObject, then create a variable equal to the method signature, set that variable to the optional method, then test the variable. This didn't seem to work. My guess is that when compiled against the iOS 8.0 SDK, the compiler knows where it thinks that method should be, so it optimizes this all down to a memory lookup. Everything works fine until I try to test the variable, at which point I get a EXC_BAD_ACCESS.

However, in the same WWDC talk where I found the gem about all methods being optional, they use Optional Chaining to call an optional method - and this seems to work. The lame part is that you have to actually attempt to call the method in order to know if it exists, which in the case of registering for notifications is a problem because you're trying to figure out if this method exists before you go creating a UIUserNotificationSettings object. It seems like calling that method with nil though is okay, so the solution that seems to be working for me is:

var ao: AnyObject = UIApplication.sharedApplication()
if let x:Void = ao.registerUserNotificationSettings?(nil) {
    // It's iOS 8
    var types = UIUserNotificationType.Badge | UIUserNotificationType.Sound | UIUserNotificationType.Alert
    var settings = UIUserNotificationSettings(forTypes: types, categories: nil)
    UIApplication.sharedApplication().registerUserNotificationSettings(settings)
} else {
    // It's older
    var types = UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound | UIRemoteNotificationType.Alert
    UIApplication.sharedApplication().registerForRemoteNotificationTypes(types)
}

After much searching related to this, the key info came from this WWDC talk https://developer.apple.com/videos/wwdc/2014/#407 right in the middle at the section about "Optional Methods in Protocols"

In Xcode 6.1 beta the above code does not work anymore, the code below works:

   if UIApplication.sharedApplication().respondsToSelector("registerUserNotificationSettings:") {
        // It's iOS 8
        var types = UIUserNotificationType.Badge | UIUserNotificationType.Sound | UIUserNotificationType.Alert
       var settings = UIUserNotificationSettings(forTypes: types, categories: nil)
       UIApplication.sharedApplication().registerUserNotificationSettings(settings)
    } else {
        // It's older
        var types = UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound | UIRemoteNotificationType.Alert
        UIApplication.sharedApplication().registerForRemoteNotificationTypes(types)
    }
查看更多
戒情不戒烟
7楼-- · 2020-01-27 09:52

Building on @Prasath's answer. This is how you do it in Swift:

if application.respondsToSelector("isRegisteredForRemoteNotifications")
{
    // iOS 8 Notifications
    application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: (.Badge | .Sound | .Alert), categories: nil));
    application.registerForRemoteNotifications()
}
else
{
    // iOS < 8 Notifications
    application.registerForRemoteNotificationTypes(.Badge | .Sound | .Alert)
}
查看更多
登录 后发表回答