user831098
user831098

Reputation: 1823

Get the push notification token - iOS 10, Swift 3

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?

Upvotes: 20

Views: 29237

Answers (10)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 120022

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

Upvotes: 0

ScottyBlades
ScottyBlades

Reputation: 14073

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

Upvotes: 6

Tim Kozak
Tim Kozak

Reputation: 4182

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

Upvotes: 0

Nikunj Kumbhani
Nikunj Kumbhani

Reputation: 3924

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

Upvotes: 1

Chirag Shah
Chirag Shah

Reputation: 3016

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

Upvotes: 38

user6880304
user6880304

Reputation: 1

It could work:

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

Thanks!

Upvotes: 0

user831098
user831098

Reputation: 1823

The below snnipet is working with Eric Aya solution :

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

Thanks for all help :)

Upvotes: 3

Etienne Martin
Etienne Martin

Reputation: 11629

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

Upvotes: 6

Ivan
Ivan

Reputation: 56

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

Upvotes: 3

Emre
Emre

Reputation: 295

var pushToken = String(format: "%@", deviceToken as CVarArg)
pushToken = pushToken.trimmingCharacters(in: CharacterSet(charactersIn: "<>"))
pushToken = pushToken.replacingOccurrences(of: " ", with: "")

Upvotes: 12

Related Questions