26

I am using this code to get the Notification Center Device token.

It was working in Swift 3 but not working in Swift 4. What changed?

if #available(iOS 10.0, *) {
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in

    }
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {    
    let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    print(deviceTokenString)
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Sandip Gill
  • 1,060
  • 1
  • 11
  • 22

9 Answers9

68

Assuming that you already checked that everything has been setup right, based on your code, it seems that it should works fine, all you have to do is to change the format to %02.2hhx instead of %02X to get the appropriate hex string. Thus you should get a valid one.

As a good practice, you could add a Data extension into your project for getting the string:

import Foundation

extension Data {
    var hexString: String {
        let hexString = map { String(format: "%02.2hhx", $0) }.joined()
        return hexString
    }
}

Usage:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let deviceTokenString = deviceToken.hexString
    print(deviceTokenString)
}
Ahmad F
  • 30,560
  • 17
  • 97
  • 143
37

Working Code for getting deviceToken in - iOS 11 or greater,

Swift 4 | Swift 5

Request user permission

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in

        // If granted comes true you can enabled features based on authorization.
        guard granted else { return }

        application.registerForRemoteNotifications()
    }        
    return true        
}

Getting device token

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    print(token) 
}

In case of error

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

    print("i am not available in simulator :( \(error)")
}
Nikunj Kumbhani
  • 3,758
  • 2
  • 26
  • 51
  • Why `application` method inside those demo code ( `Request user permission`、 `Getting device token` and `In case of error` )has different signatures?Is there exist a signature version which can handle all these situations you've mentioned above? – zionpi Jun 05 '20 at 08:55
  • @zionpi Yes You need to enable the push notification from capabilities and then registerForRemoteNotifications to Getting the token – Nikunj Kumbhani Jun 05 '20 at 09:10
  • That means those three different `application` method can be called at **ONE** single app simultaneously? @Nikunj Kumbhani – zionpi Jun 05 '20 at 09:14
  • @zionpi Yes This all is Delegate methods to Register Device for Remote Notifications – Nikunj Kumbhani Jun 05 '20 at 09:17
3

Swift 5

You can use like,

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let hexString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    print(hexString)
}
Community
  • 1
  • 1
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
1
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
    {
        let tokenChars = (deviceToken as NSData).bytes.bindMemory(to: CChar.self, capacity: deviceToken.count)
        var tokenString = ""

        for i in 0..<deviceToken.count {
            tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
        }
                    print("tokenString: \(tokenString)")
}
Uma Madhavi
  • 4,851
  • 5
  • 38
  • 73
1

To get device token

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Convert token to string
    let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
}

Hope this will help you

pkamb
  • 33,281
  • 23
  • 160
  • 191
Ganesh Manickam
  • 2,113
  • 3
  • 20
  • 28
1

You can use this both function for getting Device Token & FCM Token:


For device token use this:

func application(_ application:UIApplication,didRegisterForRemoteNotificationsWithDeviceToken 
devicetoken: Data)
 {
        let deviceTokenString = deviceToken.hexString
        print(deviceTokenString)
 }

For FCM token use this:

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
    print("Firebase registration token: \(fcmToken)")
    userDefault.set(fcmToken, forKey: "fcmToken")

}

For UUID use this:

 let deviceIds = UIDevice.current.identifierForVendor!.uuidString
Dhaval Gevariya
  • 870
  • 1
  • 12
  • 16
0

You can get the device token like this:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    print("Device Token : ",token)
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Vinoth Vino
  • 9,166
  • 3
  • 66
  • 70
0

Use Below code for getting Device token:

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

    var token = ""
    for i in 0..<deviceToken.count {
        token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
    }
    print("Device Token = \(token)")



}
Pankaj Jangid
  • 812
  • 9
  • 18
0

Not any of this solutions acceptable for me, maybe this solution will help someone, as it did to me.

/// A `String` of the Hexidecimal representation of this `Data` object
  public var hexEncodedString: String {
    // Reserver enough memory to hold all the elements
    var chars: [unichar] = []
    chars.reserveCapacity(2 * count)

    // Convert the byte data into its corresponding hex value
    for byte in self {
      chars.append(Data.utf16HexDigits[Int(byte / 16)])
      chars.append(Data.utf16HexDigits[Int(byte % 16)])
    }

    return String(utf16CodeUnits: chars, count: chars.count)
  }