web-dev-qa-db-fra.com

Comment convertir le jeton de mon appareil (NSData) en NSString?

J'implémente les notifications Push. J'aimerais enregistrer mon jeton APNS en tant que chaîne.

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

La première ligne de code affiche null. le second imprime le jeton. Comment puis-je obtenir mon newDeviceToken en tant que NSString?

135
Sheehan Alam

utilisez ceci :

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

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

Si quelqu'un cherche un moyen de faire cela à Swift:

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: pour Swift 3

Swift 3 introduit le type Data, avec une sémantique de valeur. Pour convertir la deviceToken en chaîne, procédez comme suit:

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

Quelqu'un m'a aidé avec ça. Je ne fais que passer

- (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

Vous pourriez utiliser ceci 

- (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

Pour ceux qui veulent dans Swift 3 et la méthode la plus simple

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

C'est ma solution et ça fonctionne bien dans mon application:

    NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] 
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
  • convertir NSData en NSString avec stringWithFormat
  • couper le "<>"
  • enlever les espaces
16
Zeb

Je pense que la conversion de deviceToken en chaîne d'octets hexadécimales n'a aucun sens. Pourquoi? Vous l'enverrez à votre serveur, où il sera transformé en octets pour être transmis à APNS. Utilisez donc la méthode NSData de base64EncodedStringWithOptions, transmettez-la au serveur, puis utilisez des données inversées base64 :) C'est tellement plus simple :) 

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

C'est une solution un peu plus courte:

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

Qu'en est-il d'une solution en ligne?

Objectif c

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

Rapide

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

Version Swift fonctionnelle

Bon mot:

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

Voici un formulaire d'extension réutilisable et auto-documentant:

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

Vous pouvez également utiliser reduce("", combine: +) au lieu de joinWithSeparator("") pour être perçu comme un maître fonctionnel par vos pairs.


Modification: j'ai remplacé String ($ 0, radix: 16) par String (format: "% 02x", $ 0), car un nombre à un chiffre devait avoir un zéro

(Je ne sais pas encore comment marquer une question comme un duplicata de cet autre , alors je viens de poster à nouveau ma réponse)

3
NiñoScript

Pour 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

Explication de %02.2hhx dans le vote élevé réponse :

  • %: introduit le spécificateur de conversion x.
  • 02: la largeur minimale de la valeur convertie est 2. Si la valeur convertie comporte moins d'octets que la largeur du champ, elle doit être complétée avec 0 à gauche.
  • .2: donne le nombre minimum de chiffres à afficher pour le spécificateur de conversion x.
  • hh: Spécifie que le spécificateur de conversion x s'applique à un argument de caractère signé ou non signé (l'argument aura été promu conformément aux promotions d'entier, mais sa valeur doit être convertie en caractère signé ou non signé avant impression).
  • x: L'argument non signé doit être converti au format hexadécimal non signé dans le style "dddd"; les lettres "abcdef" sont utilisées. La précision spécifie le nombre minimum de chiffres à afficher; si la valeur en cours de conversion peut être représentée avec moins de chiffres, elle doit être complétée par des zéros non significatifs. La précision par défaut est 1. Le résultat de la conversion de zéro avec une précision explicite de zéro ne doit pas contenir de caractères.

Pour plus de détails, voir Spécification IEEE printf .


Sur la base de l'explication ci-dessus, je pense qu'il est préférable de changer %02.2hhx en %02x ou %.2x.

Pour Swift 5, les méthodes suivantes sont toutes possibles:

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

Le test est le suivant:

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

L'utilisation de pdateAccumulatingResult est plus efficace que les diverses autres approches trouvées ici, voici donc le moyen le plus rapide de personnaliser votre Data octets:

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

Jeter ma réponse sur la pile. Évitez d'utiliser l'analyse des chaînes; La documentation ne garantit pas que NSData.description fonctionnera toujours de cette manière.

Mise en œuvre de Swift 3:

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

Rapide 

    // 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

J'ai essayé de tester deux méthodes différentes avec les formats "%02.2hhx" et "%02x"

    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)

et le résultat est que le plus rapide est "%02x" à une moyenne de 2,0 vs 2,6 pour la version réduite:

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

Voici comment vous le faites dans 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

Rapide:

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