2016-06-22 25 views
85

Sto provando a far funzionare la mia app in Xcode 8.0 e sto riscontrando un errore. So che questo codice ha funzionato bene nelle versioni precedenti di swift, ma suppongo che il codice per questo sia cambiato nella nuova versione. Ecco il codice che sto cercando di eseguire:Registrazione per notifiche push in Xcode 8/Swift 3.0?

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

L'errore che sto ricevendo è "etichette argomento '(forTypes :, categorie :)' non corrispondono a eventuali sovraccarichi disponibile"

C'è un comando diverso che potrei provare a far funzionare?

+2

ho scritto una guida su come fare proprio questo: https://eladnava.com/send-push-notifications-to-ios-devices-using-xcode-8-and-swift-3/ –

+1

Notifica in Swift 3.0: https://iosdevcenters.blogspot.com/2016/09/usernotifications-framework-push.html –

risposta

235

Import quadro UserNotifications e aggiungere il UNUserNotificationCenterDelegate in AppDelegate.swift

permesso dell'utente Richiesta

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 
    } 

Ottenere dispositivo Token

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

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


} 

In caso di errore

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

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

} 

Nel caso in cui avete bisogno di sapere le autorizzazioni concesse

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

      switch setttings.soundSetting{ 
      case .enabled: 

       print("enabled sound setting") 

      case .disabled: 

       print("setting has been disabled") 

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

Ottengo errore in swift 2.3: UNUserNotificationCenter non ha un membro corrente –

+0

Hay è possibile fornire il salvataggio nell'obiettivo c – Ayaz

+0

Solo una nota, non restituisce più il token del dispositivo. Almeno nel mio caso restituisce semplicemente "32 byte" –

17

In iOS10 invece del codice, si dovrebbe chiedere l'autorizzazione per la notifica con il seguente: (Non dimenticare di aggiungere il quadro UserNotifications)

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

Inoltre, il codice corretto per voi è (uso nel else della condizione precedente, per esempio):

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

Infine, assicurarsi Push Notification si attiva sotto target ->Capabilities ->Push notification . (Impostarlo su On)

+1

vedere: Pagina 73 del [Documento Apple qui] (http://devstreaming.apple.com/videos /wwdc/2016/707s77u9e6pv0dy9ggm/707/707_introduction_to_notifications.pdf) – tsnkff

+2

Grazie mille per la risposta! Usando il codice, invece, si sta dicendo "Uso dell'identificatore non risolto 'UNUserNotificationCenter'" –

+0

E grazie mille per la documentazione, blablabla! Non l'ho visto sul loro sito, sono contento che esista. : D –

36
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 :) 
       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 
} 
+1

Questo ha funzionato, a differenza del resto. Grazie. –

+0

Qual è il vantaggio aggiunto di questo nuovo framework? Quello che vedo qui è l'utilizzo dell'approccio 'completionHandler over delegate' e quindi il processo decisionale ti viene dato subito: errore, concesso o nonGrantato .... In 6 Honey

+0

perché la tua è diversa dalla risposta accettata? Ha un 'application.registerForRemoteNotifications()' * dopo * his 'center.requestAuthorization' – Honey

-1
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
    let notificationCenter = UNUserNotificationCenter.current() 
    notificationCenter.requestAuthorization([.alert , .sound]) { (finished, err) in 
     if err == nil { 
      application.registerForRemoteNotifications() 
     } 
    } 
    return true 
} 
+0

La verità è che 'error' è sempre' nil'. –

19

ho avuto problemi con le risposte qui in convertire l'oggetto DeviceToken Data in una stringa per inviare t o il mio server con la beta corrente di Xcode 8. Soprattutto quello che utilizzava deviceToken.description come in 8.0b6 che restituirebbe "32 Bytes" che non è molto utile :)

Questo è ciò che ha funzionato per me. ..

creare un'estensione su Data per implementare un metodo di "hexstring":

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

e quindi utilizzare tale quando si riceve la richiamata da registrare per le notifiche a distanza:

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

Ho anche avuto il problema "32bytes". Ottima soluzione, puoi comunque eseguire la conversione in linea senza creare un'estensione. In questo modo: 'let deviceTokenString = deviceToken.reduce (" ", {$ 0 + String (formato:"% 02X ", $ 1)})' –

+1

Assurdo che non ci sia alcuna soluzione proveniente dall'API stesso –

+1

Sì, è sempre stato bello strano che API .. sorpreso che non aggiustarlo quando si fa il nuovo framework di notifiche in iOS10 – tomwilson

0

La risposta da ast1 è molto semplice e utile. Funziona per me, grazie mille. Voglio solo farlo uscire qui, quindi le persone che hanno bisogno di questa risposta possono trovarlo facilmente. Quindi, ecco il mio codice dalla registrazione della notifica locale e remota (push).

//1. In Appdelegate: didFinishLaunchingWithOptions add these line of codes 
    let mynotif = UNUserNotificationCenter.current() 
    mynotif.requestAuthorization(options: [.alert, .sound, .badge]) {(granted, error) in }//register and ask user's permission for local notification 

    //2. Add these functions at the bottom of your AppDelegate before the last "}" 
    func application(_ application: UIApplication, didRegister notificationSettings: UNNotificationSettings) { 
     application.registerForRemoteNotifications()//register for push notif after users granted their permission for showing notification 
} 
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 
    let tokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)}) 
    print("Device Token: \(tokenString)")//print device token in debugger console 
} 
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { 
    print("Failed to register: \(error)")//print error in debugger console 
} 
7

Bene questo lavoro per me. Prima in AppDelegate

import UserNotifications 

Poi:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 
     // Override point for customization after application launch. 
     registerForRemoteNotification() 
     return true 
    } 

    func registerForRemoteNotification() { 
     if #available(iOS 10.0, *) { 
      let center = UNUserNotificationCenter.current() 
      center.delegate = self 
      center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in 
       if error == nil{ 
        UIApplication.shared.registerForRemoteNotifications() 
       } 
      } 
     } 
     else { 
      UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil)) 
      UIApplication.shared.registerForRemoteNotifications() 
     } 
    } 

Per ottenere devicetoken:

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

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

} 
11
import UserNotifications 

successivo, passare al direttore del progetto per la vostra destinazione e nella scheda Generale , cerca la sezione Linked Frameworks and Libraries.

Fare clic su + e selezionare UserNotifications.framework:

// 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]) 
} 

metodi utilizzare la notifica delegato

// 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)") 
} 

per la ricezione di notifiche push

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

Impostazione di notifiche push sta consentendo la funzione all'interno Xcode 8 per la tua app. Semplicemente vai all'editor di progetto per il tuo target e poi fai clic sulla scheda Capabilities. Cerca Notifiche push e attiva il valore su SU.

Controlla qui sotto link per maggiori notifica metodi delegato

gestione delle notifiche locali e remoti UIApplicationDelegate - gestione delle notifiche locali e remoti

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

1

semplicemente fare il seguendo in didFinishWithLaunching::

if #available(iOS 10.0, *) { 

    let center = UNUserNotificationCenter.current() 

    center.delegate = self 
    center.requestAuthorization(options: []) { _, _ in 
     application.registerForRemoteNotifications() 
    } 
} 

ricordo di istruzione import:

import UserNotifications 
+0

credo che questa dovrebbe essere la risposta accettata. Sembra corretto chiamare '' 'registerForRemoteNotifications()' '' nel gestore di completamento di '' 'requestAuthorization()' ''. Puoi anche voler registrare '' 'registerForRemoteNotifications()' '' con un'istruzione '' 'if granted''': ' '' center.requestAuthorization (opzioni: [. Badge, .alert, .sound]) { (concesso, errore) in se concesso { UIApplication.shared.registerForRemoteNotifications() } } '' ' – Bocaxica

3

Heads up, si dovrebbe utilizzare il thread principale per questa azione.

let center = UNUserNotificationCenter.current() 
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in 
     if granted { 
      DispatchQueue.main.async(execute: { 
       UIApplication.shared.registerForRemoteNotifications() 
      }) 
     } 
    } 
2

primo, ascoltare lo stato di notifica utente, vale a dire, registerForRemoteNotifications() per ottenere APN gettoniera;
Secondo, richiedere l'autorizzazione. Quando viene autorizzato dall'utente, deviceToken verrà inviato all'ascoltatore, il AppDelegate;
Terzo, segnala il token del dispositivo al server.

extension AppDelegate { 
    /// 1. 监听 deviceToken 
    UIApplication.shared.registerForRemoteNotifications() 

    /// 2. 向操作系统索要推送权限(并获取推送 token) 
    static func registerRemoteNotifications() { 
     if #available(iOS 10, *) { 
      let uc = UNUserNotificationCenter.current() 
      uc.delegate = UIApplication.shared.delegate as? AppDelegate 
      uc.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in 
       if let error = error { // 无论是拒绝推送,还是不提供 aps-certificate,此 error 始终为 nil 
        print("UNUserNotificationCenter 注册通知失败, \(error)") 
       } 
       DispatchQueue.main.async { 
        onAuthorization(granted: granted) 
       } 
      } 
     } else { 
      let app = UIApplication.shared 
      app.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil)) // 获取用户授权 
     } 
    } 

    // 在 app.registerUserNotificationSettings() 之后收到用户接受或拒绝及默拒后,此委托方法被调用 
    func application(_ app: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { 
     // 已申请推送权限,所作的检测才有效 
     // a 征询推送许可时,用户把app切到后台,就等价于默拒了推送 
     // b 在系统设置里打开推送,但关掉所有形式的提醒,等价于拒绝推送,得不token,也收不推送 
     // c 关掉badge, alert和sound 时,notificationSettings.types.rawValue 等于 0 和 app.isRegisteredForRemoteNotifications 成立,但能得到token,也能收到推送(锁屏和通知中心也能看到推送),这说明types涵盖并不全面 
     // 对于模拟器来说,由于不能接收推送,所以 isRegisteredForRemoteNotifications 始终为 false 
     onAuthorization(granted: app.isRegisteredForRemoteNotifications) 
    } 

    static func onAuthorization(granted: Bool) { 
     guard granted else { return } 
     // do something 
    } 
} 

extension AppDelegate { 
    func application(_ app: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 
     // 
    } 

    // 模拟器得不到 token,没配置 aps-certificate 的项目也得不到 token,网络原因也可能导致得不到 token 
    func application(_ app: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { 
     // 
    } 
} 
+0

come aggiungere la notifica multipla? – ArgaPK

+0

@ArgaPK, Per inviare notifiche push è ciò che fa la piattaforma del server. –