124 votes

S'enregistrer pour les notifications push dans Xcode 8/Swift 3.0 ?

J'essaie de faire fonctionner mon application en Xcode 8.0 et je me heurte à une erreur. Je sais que ce code fonctionnait bien dans les versions précédentes de Swift, mais je suppose que le code a été modifié dans la nouvelle version. Voici le code que j'essaie d'exécuter :

let settings = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil)     
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.shared().registerForRemoteNotifications()

L'erreur que j'obtiens est "Les étiquettes d'arguments '(forTypes :, categories :)' ne correspondent à aucune surcharge disponible".

Y a-t-il une autre commande que je pourrais essayer pour que cela fonctionne ?

2 votes

J'ai écrit un guide sur la façon de le faire : eladnava.com/

312voto

LC 웃 Points 15362

Importez le UserNotifications et ajoutez le UNUserNotificationCenterDelegate dans AppDelegate.swift

Demander l'autorisation de l'utilisateur

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
            // Enable or disable features based on authorization.
        }
        application.registerForRemoteNotifications()
        return true
}

Obtenir un jeton de dispositif

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

    let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    print(deviceTokenString)
}

En cas d'erreur

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {

        print("i am not available in simulator \(error)")
}

Au cas où vous auriez besoin de connaître les permissions accordées

UNUserNotificationCenter.current().getNotificationSettings(){ (settings) in

            switch settings.soundSetting{
            case .enabled:

                print("enabled sound setting")

            case .disabled:

                print("setting has been disabled")

            case .notSupported:
                print("something vital went wrong here")
            }
        }

1 votes

J'obtiens une erreur dans swift 2.3 : UNUserNotificationCenter n'a pas de membre actuel.

0 votes

Hay pouvez-vous fournir la sauvegarde en objectif c

0 votes

Juste une note, ne renvoie plus le jeton du dispositif. Au moins dans mon cas, il retourne simplement "32 bytes".

48voto

Brandon Points 4211
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    if #available(iOS 10, *) {

        //Notifications get posted to the function (delegate):  func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)"

        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in

            guard error == nil else {
                //Display Error.. Handle Error.. etc..
                return
            }

            if granted {
                //Do stuff here..

                //Register for RemoteNotifications. Your Remote Notifications can display alerts now :)
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
            else {
                //Handle user denying permissions..
            }
        }

        //Register for remote notifications.. If permission above is NOT granted, all notifications are delivered silently to AppDelegate.
        application.registerForRemoteNotifications()
    }
    else {
        let settings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(settings)
        application.registerForRemoteNotifications()
    }

    return true
}

0 votes

Quel est l'avantage supplémentaire de ce nouveau cadre ? Ce que je vois ici, c'est l'utilisation de l'approche 'completionHandler over delegate' et la prise de décision vous est donnée tout de suite : erreur, accordé ou notGranted. .... Dans 6< iOS <10 vous deviez faire application.isRegisteredForRemoteNotifications() pour voir si elle est accordée, et utiliser une autre méthode déléguée au cas où vous auriez une erreur. Pas vrai ? Quelque chose d'autre ?

0 votes

Pourquoi votre réponse est-elle différente de la réponse acceptée ? Il a un application.registerForRemoteNotifications() après son center.requestAuthorization

1 votes

@Honey ; C'est ajouté si vous voulez activer les notifications "à distance". Lorsque j'ai écrit ma réponse, aucune autre réponse n'existait et @OP n'a pas précisé s'il voulait un support à distance ou local ou iOS 10, alors j'ai ajouté autant que possible. Note : Vous ne devriez pas enregistrer les RemoteNotifications tant que l'utilisateur n'a pas accordé l'accès (sinon toutes les notifications à distance sont délivrées silencieusement [sauf si c'est ce que vous voulez] -- pas de popups). De plus, l'avantage de la nouvelle API est qu'elle supporte les pièces jointes. En d'autres termes, vous pouvez ajouter des GIF et d'autres images, des vidéos, etc. à vos notifications.

28voto

Jaleel Nazir Points 3864
import UserNotifications  

Ensuite, allez dans l'éditeur de projet de votre cible, et dans l'onglet Général, recherchez la section Cadres et bibliothèques liés.

Cliquez sur + et sélectionnez UserNotifications.framework :

// iOS 12 support
if #available(iOS 12, *) {  
    UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound, .provisional, .providesAppNotificationSettings, .criticalAlert]){ (granted, error) in }
    application.registerForRemoteNotifications()
}

// iOS 10 support
if #available(iOS 10, *) {  
    UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
    application.registerForRemoteNotifications()
}
// iOS 9 support
else if #available(iOS 9, *) {  
    UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
    UIApplication.shared.registerForRemoteNotifications()
}
// iOS 8 support
else if #available(iOS 8, *) {  
    UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
    UIApplication.shared.registerForRemoteNotifications()
}
// iOS 7 support
else {  
    application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}

Utiliser les méthodes de délégation de notification

// Called when APNs has assigned the device a unique token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {  
    // Convert token to string
    let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    print("APNs device token: \(deviceTokenString)")
}

// Called when APNs failed to register the device for push notifications
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {  
    // Print the error to console (you should alert the user that registration failed)
    print("APNs registration failed: \(error)")
}

Pour recevoir une notification push

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    completionHandler(UIBackgroundFetchResult.noData)
}

Configurer les notifications push, c'est activer la fonction dans Xcode 8. pour votre application. Il suffit d'aller sur allez dans l'éditeur de projet de votre cible et ensuite cliquez sur le Onglet Capacités . Cherchez Notifications push et de basculer sa valeur à ON .

Vérifiez le lien ci-dessous pour plus de méthodes de délégués de notification

Gestion des notifications locales et distantes UIApplicationDelegate - Gestion des notifications locales et distantes

https://developer.apple.com/reference/uikit/uiapplicationdelegate

20voto

tomwilson Points 521

J'ai eu des problèmes avec les réponses ici pour convertir l'objet deviceToken Data en une chaîne de caractères à envoyer à mon serveur avec la version bêta actuelle de Xcode 8. Surtout celle qui utilisait deviceToken.description comme dans 8.0b6 qui retournait "32 Bytes" ce qui n'est pas très utile :)

C'est ce qui a marché pour moi...

Créez une extension sur Data pour implémenter une méthode "hexString" :

extension Data {
    func hexString() -> String {
        return self.reduce("") { string, byte in
            string + String(format: "%02X", byte)
        }
    }
}

Et ensuite, utilisez-le lorsque vous recevez le rappel de l'enregistrement des notifications à distance :

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let deviceTokenString = deviceToken.hexString()
    // Send to your server here...
}

8 votes

J'avais aussi le problème des "32bytes". Excellente solution, vous pouvez faire la conversion en ligne sans créer d'extension. Comme ceci : let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})

1 votes

Il est absurde qu'aucune solution ne vienne de l'API elle-même.

1 votes

Oui, cette API a toujours été assez bizarre. Je suis surpris qu'ils ne l'aient pas corrigée lors de la création du nouveau cadre de notifications dans iOS10.

18voto

tsnkff Points 538

Dans iOS10, à la place de votre code, vous devez demander une autorisation pour la notification avec ce qui suit : (N'oubliez pas d'ajouter l'élément UserNotifications Cadre)

if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().requestAuthorization([.alert, .sound, .badge]) { (granted: Bool, error: NSError?) in
            // Do something here
        }
    }

De plus, le code correct pour vous est (utiliser dans la section else de la condition précédente, par exemple) :

let setting = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared().registerUserNotificationSettings(setting)
UIApplication.shared().registerForRemoteNotifications()

Enfin, assurez-vous que Push Notification est activé sous target -> Capabilities -> Push notification . (le mettre sur On )

1 votes

Voir : Page 73 du Apple Doc ici

2 votes

Merci beaucoup pour la réponse ! En utilisant le code, cependant, il dit "Use of unresolved identifier 'UNUserNotificationCenter'".

0 votes

Et merci beaucoup pour la documentation, blablabla ! Je n'avais pas vu ça sur leur site, je suis content que ça existe :D

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