20

How to get the device token from new xCode 8, Swift 3 in iOS 10?

Here is the code to register notification:

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

    DispatchQueue.main.async {
        let settings = UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(settings)
    }
    return true
}

func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {

    if notificationSettings.types != UIUserNotificationType() {
        application.registerForRemoteNotifications()
    }
}

Here i get the token, but i get the following error

Cannot invoke initializer for type 'UnsafePointer<CChar>' with an argument list of type '(UnsafeRawPointer)':

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

    let chars = UnsafePointer<CChar>((deviceToken as NSData).bytes)
    var token = ""

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

    print("Registration succeeded!")
    print("Token: ", token)
}

Can anyone help me solve it?

Ricardo Dias Morais
  • 1,947
  • 3
  • 18
  • 36
user831098
  • 1,803
  • 6
  • 27
  • 47
  • Possible duplicate of http://stackoverflow.com/questions/37956482/registering-for-push-notifications-in-xcode-8-swift-3-0 – Eric Aya Sep 19 '16 at 09:15
  • You can follow this link its in objective C but you can get some idea http://stackoverflow.com/questions/39572897/ios-10-push-notification-issue-solved – Darshan Mothreja Sep 19 '16 at 14:10

10 Answers10

38

This method may solve your problem in iOS 10 and greater:

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(token)
}
Chirag Shah
  • 3,034
  • 1
  • 30
  • 61
  • I didn't downvote. But perhaps because there is no explanation for why/how `Data` needs to be converted to a `String` like this – mfaani Feb 27 '19 at 22:56
12
var pushToken = String(format: "%@", deviceToken as CVarArg)
pushToken = pushToken.trimmingCharacters(in: CharacterSet(charactersIn: "<>"))
pushToken = pushToken.replacingOccurrences(of: " ", with: "")
Emre
  • 295
  • 2
  • 9
6

Swift 3 example taken from raywenderlich.com.

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data){
    let tokenParts = deviceToken.map { data -> String in
        return String(format: "%02.2hhx", data)
    }  
    let token = tokenParts.joined()
    print(token)
}
Etienne Martin
  • 10,018
  • 3
  • 35
  • 47
6

One line:

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

From this tutorial.

Or a modular/encapsulated/OOP way:

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

Then you can do this:

let token = deviceToken.string
ScottyBlades
  • 12,189
  • 5
  • 77
  • 85
3

The below snnipet is working with Eric Aya solution :

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

Thanks for all help :)

Jigar Tarsariya
  • 3,189
  • 3
  • 14
  • 38
user831098
  • 1,803
  • 6
  • 27
  • 47
3

Faced the same problem, this is the only thing that helped me:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = String(format: "%@", deviceToken as CVarArg)
        .trimmingCharacters(in: CharacterSet(charactersIn: "<>"))
        .replacingOccurrences(of: " ", with: "")
}
Ivan
  • 56
  • 2
1

Working Code for getting push notification token - iOS 11 or greater, Swift 4

Request user permission

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

    let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert,UIUserNotificationType.badge, UIUserNotificationType.sound]
    let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)

    application.registerUserNotificationSettings(pushNotificationSettings)
    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
0

It could work:

let chars = UnsafePointer<CChar>((deviceToken as NSData).bytes.assumingMemoryBound(to:CChar.self))

Thanks!

Jigar Tarsariya
  • 3,189
  • 3
  • 14
  • 38
0

Code from Mixpanel library

    let tokenChars = (deviceToken as NSData).bytes.assumingMemoryBound(to: CChar.self)
    var tokenString = ""
    for i in 0..<deviceToken.count {
        tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
    }
Tim Kozak
  • 4,026
  • 39
  • 44
0

Since you may need this token in different methods (like firebase, web engage, branch, etc), you can use a custom class to initial an APNS from the data containing both data and string

public class APNS {
    public init(deviceToken data: Data) {
        self.data = data
        self.string = data.map { data in String(format: "%02.2hhx", data) } .joined()
    }

    public let data: Data
    public let string: String
}

then you can use it anywhere you need:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = APNS(deviceToken: deviceToken)
    print(token.string)
}
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278