Schnelle 3-Geräte-Token werden jetzt als "32BYTES" analysiert.


94

Ich habe gerade von Xcode 7 auf 8 GM aktualisiert und inmitten der Swift 3-Kompatibilitätsprobleme festgestellt, dass meine Gerätetoken nicht mehr funktionieren. Sie lesen jetzt nur noch '32BYTES'.

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
    print(deviceToken) // Prints '32BYTES'
    print(String(data: deviceToken , encoding: .utf8)) // Prints nil
}

Vor dem Update konnte ich die NSData einfach an meinen Server senden, aber jetzt fällt es mir schwer, das Token tatsächlich zu analysieren.

Was vermisse ich hier?

Bearbeiten: Ich teste gerade die Konvertierung zurück zu NSData und sehe die erwarteten Ergebnisse. Jetzt bin ich nur noch verwirrt über den neuen Datentyp.

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
    print(deviceToken) // Prints '32BYTES'
    print(String(data: deviceToken , encoding: .utf8)) // Prints nil

    let d = NSData(data: deviceToken)
    print(d) // Prints my device token
}

2
Ändern, um NSDataeinfach das descriptionvon zu drucken NSData. Daraus ergibt sich immer noch kein String.
rmaddy

Antworten:


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

Die inverse Operation (hex String -> Data) ist hier verfügbar: stackoverflow.com/a/46663290/5252428
Rok Gregorič

4
%02xist auch okay.
jqgsninimo

1
@Rok kannst du bitte deine antwort erklären In welchem ​​neuen Format wurde das Token formatiert?
Simo

@simo ist eine Konvertierung von Daten in eine hexadezimale Zeichenfolge, die Sie an einen Webdienst / eine Web-API übergeben können, um Push-Benachrichtigungen senden zu können.
Rok Gregorič

Ein guter Beitrag mit einer guten Erklärung der Unterschiede zwischen %02.2hhxund %02x nshipster.com/apns-device-tokens/#overturned-in-ios-13
Rok Gregorič

35

Ich hatte das gleiche Problem. Das ist meine Lösung:

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

1
Dies ist ein alternativer Ansatz zum Codieren von NSDatain eine Zeichenfolge. Ich schlug vor, in meiner Antwort die Base64-Codierung zu verwenden. Dies verwendet die Base16-Codierung.
rmaddy

@rmaddy dein Weg ist auch interessant, aber es wäre hilfreicher, wenn du uns eine Anleitung mit Code gibst !!!
Vivek Agravat

29

Hier ist meine Swift 3-Erweiterung, um eine Base-16-codierte Hex-Zeichenfolge zu erhalten:

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

Ich habe festgestellt, dass das Format "% 02x" auch funktioniert. Ich kann auch nicht verstehen, was "hh" tut
andrei

1
@andrei "hh" weist den String-Formatierer an, die Eingabe als Zeichen zu behandeln. In Kürze ist Data jedoch eine Sammlung von UInt8, sodass Sie es nicht benötigen
wyu

27

Das Geräte-Token war noch nie eine Zeichenfolge und schon gar nicht eine UTF-8-codierte Zeichenfolge. Es sind Daten. Es sind 32 Bytes undurchsichtiger Daten.

Die einzig gültige Möglichkeit, die undurchsichtigen Daten in eine Zeichenfolge zu konvertieren, besteht darin, sie zu codieren - normalerweise über eine Base64-Codierung.

Verwenden Sie in Swift 3 / iOS 10 einfach die Data base64EncodedString(options:)Methode.


Nun, der Unterschied hier ist der neue Datentyp. Ich habe gerade versucht, das deviceToken in NSData zu konvertieren, und es druckt jetzt mein Geräte-Token wie zuvor. Haben Sie ein Beispiel, wie Sie ohne NSData damit umgehen würden? Weil sich das hackig anfühlt, aber auch einfacher als das, was sie von uns zu erwarten scheinen.
user1537360

3
Ich stehe zu dem, was ich gesagt habe. NSDataoder Dataes spielt keine Rolle. Die Bytes der Daten sind keine Zeichenfolge und waren es auch nie. In der Dokumentation wird eindeutig angegeben, dass es sich um einen undurchsichtigen Datensatz handelt. Die Tatsache, dass Ihr Code früher funktioniert hat, ist Glück. Es war immer die falsche Art, damit umzugehen. Konvertieren Sie einfach die Daten in eine Zeichenfolge, indem base64 die Daten codiert. Das ist jetzt und früher die richtige Lösung.
rmaddy

Die Base64-Dekodierung funktioniert nicht, wenn Sie einen Dienst wie Amazon SNS verwenden. Lösungen, die die Daten in hexadezimale Zeichen konvertieren, wie z. B. @satheeshwaran , erzeugen Geräte-Token-Zeichenfolgen, die denen vor den Änderungen am SDK ähneln.
Alexander

@ Alexander Wer hat etwas über Base64-Dekodierung gesagt? Der springende Punkt der Frage und der Antworten ist, die Rohdaten zu codieren , nicht zu dekodieren, in eine Zeichenfolge. Der einzige Grund, dies zu tun, ist das Anzeigen der Rohdaten. Das spezifische Codierungsschema ist irrelevant. Die andere Antwort verwendet die Basis-16-Codierung. Ich erwähnte die Verwendung der Base 64-Codierung.
rmaddy

@rmaddy Ich meinte Base64-Codierung in meinem Kommentar, ich entschuldige mich.
Alexander

15

Versuche dies:

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

   let token = String(data: deviceToken.base64EncodedData(), encoding: .utf8)?.trimmingCharacters(in: CharacterSet.whitespaces).trimmingCharacters(in: CharacterSet(charactersIn: "<>")) 
}

2
Es scheint, dass es jetzt andere Token
zurückgibt

8

Versuche dies

if #available(iOS 10.0, *) {
   let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
}

7

Swift 3

Der beste und einfachste Weg.

deviceToken.base64EncodedString()

3
Dies ist am einfachsten, aber seien Sie vorsichtig, was Ihr Server verwendet, wenn Sie das Token übergeben. Viele APIs erwarten mit Hex-Codierung oder Base-16. Zum Beispiel Django Push-Benachrichtigungen.
sww314

4

Diese Antwort wurde nicht als offizielle Antwort angegeben (siehe in einem Kommentar), aber ich habe sie letztendlich getan, um mein Token wieder in Ordnung zu bringen.

let tokenData = deviceToken as NSData
let token = tokenData.description

// remove any characters once you have token string if needed
token = token.replacingOccurrences(of: " ", with: "")
token = token.replacingOccurrences(of: "<", with: ""
token = token.replacingOccurrences(of: ">", with: "")

Für die Zwecke unserer Backend-API (Python) war dies die "sauberste" Lösung ¯ \ _ (ツ) _ / ¯
race_carr

1
Dies funktioniert unter iOS 10 nicht. Die Beschreibung gibt jetzt nur noch "32 Byte" zurück.
Edopelawi

@edopelawi du hast vergessen dort zu setzen as NSData. Wenn Sie als NSData not Data angeben, wird der korrekte Wert auch unter iOS 10 zurückgegeben
Jakub

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

    let token = deviceToken.map({ String(format: "%02.2hhx", $0)}).joined()
     print("TOKEN: " + token)


}

4
Während dieser Codeblock die Frage beantworten kann, ist es am besten, wenn Sie eine kleine Erklärung dafür geben könnten, warum dies so ist.
Crispin

3

Ich habe das gerade gemacht,

let token = String(format:"%@",deviceToken as CVarArg).components(separatedBy: CharacterSet.alphanumerics.inverted).joined(separator: "")

es gab das gleiche Ergebnis wie,

let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()

0

Holen Sie sich das Gerätetoken mit dem richtigen Format.

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 
{
            var formattedToken = ""
            for i in 0..<deviceToken.count {
                formattedToken = formattedToken + String(format: "%02.2hhx", arguments: [deviceToken[i]])
            }
            print(formattedToken)
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.