it-swarm.com.de

Wie kann ich mein Gerätetoken (NSData) in einen NSString konvertieren?

Ich implementiere Push-Benachrichtigungen. Ich möchte mein APNS-Token als String speichern.

- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken
{
    NSString *tokenString = [NSString stringWithUTF8String:[newDeviceToken bytes]]; //[[NSString alloc]initWithData:newDeviceToken encoding:NSUTF8StringEncoding];
    NSLog(@"%@", tokenString);
    NSLog(@"%@", newDeviceToken);
}

Die erste Codezeile gibt null aus. Die Sekunde druckt das Token. Wie bekomme ich mein neuesDeviceToken als NSString?

135
Sheehan Alam

benutze das :

NSString * deviceTokenString = [[[[deviceToken description]
                         stringByReplacingOccurrencesOfString: @"<" withString: @""] 
                        stringByReplacingOccurrencesOfString: @">" withString: @""] 
                       stringByReplacingOccurrencesOfString: @" " withString: @""];

NSLog(@"The generated device token string is : %@",deviceTokenString);
66
kulss

Wenn jemand nach einem Weg sucht, dies in Swift zu tun:

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
    var tokenString = ""

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

    print("tokenString: \(tokenString)")
}

Edit: Für Swift 3

Swift 3 führt den Typ Data mit Wertsemantik ein. So konvertieren Sie die Variable deviceToken in einen String:

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

Jemand hat mir dabei geholfen. Ich gehe einfach weiter

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {

    const unsigned *tokenBytes = [deviceToken bytes];
    NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
                         ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
                         ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
                         ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];

    [[MyModel sharedModel] setApnsToken:hexToken];
}
152
Shubhank

Du könntest das benutzen 

- (NSString *)stringWithDeviceToken:(NSData *)deviceToken {
    const char *data = [deviceToken bytes];
    NSMutableString *token = [NSMutableString string];

    for (NSUInteger i = 0; i < [deviceToken length]; i++) {
        [token appendFormat:@"%02.2hhX", data[i]];
    }

    return [token copy];
}
95
Vlad Polyanskiy

Für diejenigen, die in Swift 3 und die einfachste Methode wollen

func extractTokenFromData(deviceToken:Data) -> String {
    let token = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    return token.uppercased();
}
34
Anand

Es ist meine Lösung und funktioniert gut in meiner App:

    NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] 
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
  • konvertieren Sie NSData in NSString mit stringWithFormat
  • das "<>" trimmen
  • entferne die Leerzeichen
16
Zeb

Ich denke, das Konvertieren von deviceToken in einen Hex-Byte-String hat keinen Sinn. Warum? Sie senden es an Ihr Backend, wo es in Bytes umgewandelt wird, die an APNS weitergeleitet werden. Verwenden Sie also die Methode base64EncodedStringWithOptions von NSData , schieben Sie sie auf den Server und verwenden Sie dann reverse base64-decodierte Daten :) Das ist so viel einfacher :) 

NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
5
Oleg Shanyuk

Dies ist eine etwas kürzere Lösung:

NSData *token = // ...
const uint64_t *tokenBytes = token.bytes;
NSString *hex = [NSString stringWithFormat:@"%016llx%016llx%016llx%016llx",
                 ntohll(tokenBytes[0]), ntohll(tokenBytes[1]),
                 ntohll(tokenBytes[2]), ntohll(tokenBytes[3])];
4
k06a

Was ist eine einzeilige Lösung?

Ziel c

NSString *token = [[data.description componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet]invertedSet]]componentsJoinedByString:@""];

Schnell

let token = data.description.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet).joinWithSeparator("")
3

Funktionelle Swift-Version

Einzeiler:

let hexString = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes),
count: data.length).map { String(format: "%02x", $0) }.joinWithSeparator("")

Hier ist eine wiederverwendbare und selbstdokumentierende Erweiterungsform:

extension NSData {
    func base16EncodedString(uppercase uppercase: Bool = false) -> String {
        let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes),
                                                count: self.length)
        let hexFormat = uppercase ? "X" : "x"
        let formatString = "%02\(hexFormat)"
        let bytesAsHexStrings = buffer.map {
            String(format: formatString, $0)
        }
        return bytesAsHexStrings.joinWithSeparator("")
    }
}

Alternativ können Sie reduce("", combine: +) anstelle von joinWithSeparator("") verwenden, um von Ihren Kollegen als funktioneller Master betrachtet zu werden.


Bearbeiten: Ich habe String ($ 0, Radix: 16) in String (Format: "% 02x", $ 0) geändert, da einstellige Zahlen eine Auffüllnullung benötigen

(Ich weiß noch nicht, wie ich eine Frage als Duplikat von dieser anderen kennzeichnen soll, also habe ich gerade meine Antwort gepostet.)

3
NiñoScript

Für Swift:

var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" )
    var deviceTokenString: String = ( deviceToken.description as NSString )
    .stringByTrimmingCharactersInSet( characterSet )
    .stringByReplacingOccurrencesOfString( " ", withString: "" ) as String

println( deviceTokenString )
1
Adarsh G J

Erklärung von %02.2hhx in der hohen Abstimmung Antwort :

  • %: Führt den Konvertierungsspezifizierer x ein.
  • 02: Die minimale Breite des konvertierten Werts ist 2. Wenn der konvertierte Wert weniger Bytes als die Feldbreite enthält, muss links 0 eingefügt werden.
  • .2: Gibt die Mindestanzahl von Stellen an, die für den Konvertierungsspezifizierer x angezeigt werden sollen.
  • hh: Gibt an, dass der Konvertierungsspezifizierer x auf ein vorzeichenbehaftetes Zeichen oder ein vorzeichenloses Zeichen angewendet wird (das Argument wurde gemäß den ganzzahligen Promotions hochgestuft, aber sein Wert wird vor dem Drucken in vorzeichenbehaftetes Zeichen oder vorzeichenbehaftetes Zeichen umgewandelt).
  • x: Das Argument ohne Vorzeichen muss in ein Hexadezimalformat ohne Vorzeichen im Stil "dddd" konvertiert werden. Die Buchstaben "abcdef" werden verwendet. Die Genauigkeit gibt die Mindestanzahl der anzuzeigenden Stellen an. Wenn der zu konvertierende Wert in weniger Ziffern dargestellt werden kann, muss er mit führenden Nullen erweitert werden. Die Standardgenauigkeit ist 1. Das Ergebnis der Konvertierung von Null mit einer expliziten Genauigkeit von Null darf keine Zeichen enthalten.

Weitere Einzelheiten finden Sie in der IEEE printf-Spezifikation .


Aufgrund der obigen Erklärung halte ich es für besser, %02.2hhx in %02x oder %.2x zu ändern.

Für Swift 5 sind alle folgenden Methoden möglich:

deviceToken.map({String(format: "%02x", $0)}).joined()
deviceToken.map({String(format: "%.2x", $0)}).joined()
deviceToken.reduce("", {$0 + String(format: "%02x", $1)})
deviceToken.reduce("", {$0 + String(format: "%.2x", $1)})

Der Test ist wie folgt:

let deviceToken = (0..<32).reduce(Data(), {$0 + [$1]})
print(deviceToken.reduce("", {$0 + String(format: "%.2x", $1)}))
// Print content:
// 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
1
jqgsninimo

Die Verwendung von pdateAccumulatingResult ist effizienter als die verschiedenen anderen hier vorkommenden Ansätze. Hier ist also die schnellste Möglichkeit, Ihre Data Bytes zu stringifizieren:

func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.reduce(into: "") { $0 += String(format: "%.2x", $1) }
    print(token)
}
1
Alex Curylo

Meine Antwort auf den Haufen werfen. Vermeiden Sie das String-Parsing. In den Dokumenten wird nicht garantiert, dass NSData.description immer auf diese Weise funktioniert.

Swift 3 Implementierung:

extension Data {
    func hexString() -> String {
        var bytesPointer: UnsafeBufferPointer<UInt8> = UnsafeBufferPointer(start: nil, count: 0)
        self.withUnsafeBytes { (bytes) in
            bytesPointer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(bytes), count:self.count)
        }
        let hexBytes = bytesPointer.map { return String(format: "%02hhx", $0) }
        return hexBytes.joined()
    }
}
1
swift taylor

Schnell 

    // make sure that we have token for the devie on the App
    func application(application: UIApplication
        , didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {

            var tokenStr = deviceToken.description
            tokenStr = tokenStr.stringByReplacingOccurrencesOfString("<", withString: "", options: [], range: nil)
            tokenStr = tokenStr.stringByReplacingOccurrencesOfString(">", withString: "", options: [], range: nil)
            tokenStr = tokenStr.stringByReplacingOccurrencesOfString(" ", withString: "", options: [], range: nil)



            print("my token is: \(tokenStr)")

    }
0
Vinod Joshi

Ich habe versucht, zwei verschiedene Methoden mit dem Format "%02.2hhx" und "%02x" zu testen.

    var i :Int = 0
    var j: Int = 0
    let e: Int = Int(1e4)
    let time = NSDate.timeIntervalSinceReferenceDate
    while i < e {
        _ =  deviceToken.map { String(format: "%02x", $0) }.joined()
        i += 1
    }
    let time2 = NSDate.timeIntervalSinceReferenceDate
    let delta = time2-time
    print(delta)

    let time3 = NSDate.timeIntervalSinceReferenceDate
    while j < e {
        _ =  deviceToken.reduce("", {$0 + String(format: "%02x", $1)})
        j += 1
    }
    let time4 = NSDate.timeIntervalSinceReferenceDate
    let delta2 = time4-time3
    print(delta2)

und das Ergebnis ist, dass der schnellste "%02x" im Durchschnitt 2,0 gegenüber 2,6 für die reduzierte Version ist:

deviceToken.reduce("", {$0 + String(format: "%02x", $1)})
0
Nicolas Manzini

So geht's in Xamarin.iOS

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    var tokenStringBase64 = deviceToken.GetBase64EncodedString(NSDataBase64EncodingOptions.None);
    //now you can store it for later use in local storage
}
0
HeisenBerg

Schnell:

let tokenString = deviceToken.description.stringByReplacingOccurrencesOfString("[ <>]", withString: "", options: .RegularExpressionSearch, range: nil)
0
Tony