210 votes

registerForRemoteNotificationTypes : n'est pas pris en charge dans iOS 8.0 et les versions ultérieures

Lorsque vous essayez de vous inscrire aux notifications push sous iOS 8.x :

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

Je reçois l'erreur suivante :

registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later.

Avez-vous une idée de la nouvelle façon de procéder ? Cela fonctionne lorsque j'exécute cette application Swift sur iOS 7.x.

EDIT

Sous iOS 7.x, lorsque j'inclus le code conditionnel, j'obtiens (soit SystemVersion conditionnelle, soit #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)

dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings

1 votes

Regardez la documentation de UIApplication, je pense que vous êtes censé utiliser registerUserNotificationSettings et registerForRemoteNotifications.

3 votes

Merci, je vais vérifier ça lundi.

0 votes

@Skyte : Cette méthode n'est disponible que dans iOS 8+.

334voto

Prasath Points 1830

Pour 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;
}

Pour iOS10

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

0 votes

Pourquoi ne pas appeler registerForRemoteNotifications à partir du callback de registerUserNotificationSettings, si vous voulez vraiment vous assurer que vous n'envoyez pas votre première notification avant d'avoir obtenu les autorisations de l'utilisateur pour afficher les alertes ?

5 votes

Plutôt que de vérifier le systemVersion vous devez vérifier [[UIApplication sharedApplication] respondsToSelector:@selector(isRegisteredForRemoteNotificati‌​ons)]

1 votes

[[UIApplication sharedApplication] registerForRemoteNotifications]; n'ira pas non plus à application:didRegisterForRemoteNotificationsWithDeviceToken‌​: ou application:didFailToRegisterForRemoteNotificationsWithError‌​: si un utilisateur a désactivé l'option "Autoriser les notifications" dans Paramètres -> Notifications -> <Mon application>.

145voto

matt--- Points 1133

Comme vous l'avez décrit, vous devrez utiliser une méthode différente en fonction des différentes versions d'iOS. Si votre équipe utilise à la fois Xcode 5 (qui ne connaît pas les sélecteurs iOS 8) et Xcode 6, vous devrez utiliser la compilation conditionnelle comme suit :

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    // use registerUserNotificationSettings
} else {
    // use registerForRemoteNotificationTypes:
}
#else
// use registerForRemoteNotificationTypes:
#endif

Si vous n'utilisez que Xcode 6, vous pouvez vous contenter de cela :

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    // use registerUserNotificationSettings
} else {
    // use registerForRemoteNotificationTypes:
}

La raison en est que la façon dont vous obtenez les autorisations de notification a changé dans iOS 8. A UserNotification est un message affiché à l'utilisateur, qu'il provienne de l'extérieur ou de l'intérieur. Vous devez obtenir la permission d'en afficher un. Ceci est décrit dans la vidéo de la WWDC 2014 "Quoi de neuf dans les notifications d'iOS"

11 votes

@Matt - Avez-vous une référence sur la raison pour laquelle Apple a cassé l'API précédente pour obtenir des permissions pour envoyer des push dans iOS8 ? J'ai fait la même chose dans mon code, mais j'ai besoin de partager une documentation officielle pour expliquer cela aux autres membres de mon entreprise.

3 votes

@KrisSubramanian La meilleure référence que j'ai est la documentation de pré-version : "Les apps qui utilisent des alertes visibles ou audibles en conjonction avec une notification locale ou push doivent enregistrer les types d'alertes qu'elles emploient." Quant au "pourquoi", je n'ai que mon interprétation : la commodité pour l'utilisateur final de ne pas être dérangé par les messages, quelle que soit leur source.

2 votes

Vous ne pouvez pas utiliser __IPHONE_OS_VERSION_MAX_ALLOWED pour vérifier cela, car c'est une vérification au moment de la compilation.

23voto

Austen Chongpison Points 1374

S'appuyant sur la réponse de @Prasath. Voici comment procéder dans 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)
}

14voto

Jeff Holliday Points 252

IOS 8 a modifié l'enregistrement des notifications d'une manière non rétrocompatible. Bien que vous deviez prendre en charge iOS 7 et 8 (et que les applications construites avec le SDK 8 ne soient pas acceptées), vous pouvez vérifier les sélecteurs dont vous avez besoin et les appeler conditionnellement et correctement pour la version en cours.

Voici une catégorie sur UIApplication qui cachera cette logique derrière une interface propre pour vous qui fonctionnera à la fois dans Xcode 5 et Xcode 6.

En-tête :

//Call these from your application code for both iOS 7 and 8
//put this in the public header
@interface UIApplication (RemoteNotifications)

- (BOOL)pushNotificationsEnabled;
- (void)registerForPushNotifications;

@end

Mise en œuvre :

//these declarations are to quiet the compiler when using 7.x SDK
//put this interface in the implementation file of this category, so they are
//not visible to any other code.
@interface NSObject (IOS8)

- (BOOL)isRegisteredForRemoteNotifications;
- (void)registerForRemoteNotifications;

+ (id)settingsForTypes:(NSUInteger)types categories:(NSSet*)categories;
- (void)registerUserNotificationSettings:(id)settings;

@end

@implementation UIApplication (RemoteNotifications)

- (BOOL)pushNotificationsEnabled
{
    if ([self respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
    {
        return [self isRegisteredForRemoteNotifications];
    }
    else
    {
        return ([self enabledRemoteNotificationTypes] & UIRemoteNotificationTypeAlert);
    }
}

- (void)registerForPushNotifications
{
    if ([self respondsToSelector:@selector(registerForRemoteNotifications)])
    {
        [self registerForRemoteNotifications];

        Class uiUserNotificationSettings = NSClassFromString(@"UIUserNotificationSettings");

        //If you want to add other capabilities than just banner alerts, you'll need to grab their declarations from the iOS 8 SDK and define them in the same way.
        NSUInteger UIUserNotificationTypeAlert   = 1 << 2;

        id settings = [uiUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert categories:[NSSet set]];            
        [self registerUserNotificationSettings:settings];

    }
    else
    {
        [self registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert];
    }
}

@end

5 votes

Je n'arrive pas à croire pourquoi Apple et les développeurs ne font pas ce genre de choses à chaque fois qu'Apple déprécie une méthode. Chaque nouvelle version d'iOS, c'est la même chose. C'est triste d'avoir à réécrire du code juste parce qu'Apple déprécie les anciennes méthodes.

2 votes

Je pense que c'est pour que les choses s'améliorent au fil du temps au lieu d'ajouter des pansements sur de vieilles croûtes comme d'autres systèmes d'exploitation auxquels je pense.

0 votes

D'après mes tests (qui ont pris une journée entière), si je me rends à l'adresse suivante Settings et désactiver les notifications, isRegisteredForRemoteNotifications revient toujours YES

3voto

jackcook Points 350

Je n'ai pas réussi à comprendre à quoi doit correspondre la variable NSSet "categories". Si quelqu'un peut me renseigner, je modifierai ce message avec plaisir. Ce qui suit fait cependant apparaître la boîte de dialogue de notification push.

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

Edit : J'ai obtenu une notification push à envoyer à mon téléphone avec ce code, donc je ne suis pas sûr que le paramètre categories soit nécessaire.

0 votes

Oui, cela fonctionne sous iOS8, mais comment le rendre compatible avec iOS7 ? Sous iOS7, il y a un plantage. La vérification de la version d'iOS n'est d'aucune utilité car iOS7 ne reconnaît pas les nouveaux symboles.

2 votes

categories est utilisé pour configurer les actions de notification dans iOS 8. Vous pouvez voir la vidéo de la WWDC 2014 "Quoi de neuf dans les notifications d'iOS" pour plus de détails

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X