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?
utilisez ceci :
NSString * deviceTokenString = [[[[deviceToken description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""];
NSLog(@"The generated device token string is : %@",deviceTokenString);
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)")
}
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)
}
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];
}
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];
}
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();
}
C'est ma solution et ça fonctionne bien dans mon application:
NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
NSData
en NSString
avec stringWithFormat
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];
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])];
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("")
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)
Pour Swift:
var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" )
var deviceTokenString: String = ( deviceToken.description as NSString )
.stringByTrimmingCharactersInSet( characterSet )
.stringByReplacingOccurrencesOfString( " ", withString: "" ) as String
println( deviceTokenString )
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
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)
}
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()
}
}
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)")
}
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)})
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
}
Rapide:
let tokenString = deviceToken.description.stringByReplacingOccurrencesOfString("[ <>]", withString: "", options: .RegularExpressionSearch, range: nil)