iphone objective-c cocoa-touch nsstring nsdata

iphone - ¿Cómo puedo convertir mi token de dispositivo(NSData) en un NSString?



objective-c cocoa-touch (22)

Estoy implementando notificaciones push. Me gustaría guardar mi Token APNS como una cadena.

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

La primera línea de código imprime nulo. el segundo imprime el token. ¿Cómo puedo obtener mi newDeviceToken como NSString?


Versión funcional Swift

Un trazador de líneas:

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

Aquí hay un formulario de extensión que se puede reutilizar y autoeducar:

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

Alternativamente, utilice reduce("", combine: +) lugar de joinWithSeparator("") para que sus pares lo vean como un maestro funcional.

Editar: Cambié String ($ 0, radix: 16) a String (formato: "% 02x", $ 0), porque los números de un dígito necesitan tener un relleno cero

(Todavía no sé cómo marcar una pregunta como un duplicado de esta otra , así que acabo de publicar mi respuesta nuevamente)


¿Qué tal una solución de línea?

C objetivo

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

Rápido

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


Alguien me ayudó con esto. Solo estoy pasando

- (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]; }


Creo que la conversión de dispositivoToken a cadena de bytes hexadecimales no tiene sentido. ¿Por qué? Lo enviarás a tu backend, donde se transformará en bytes para enviarlo a APNS. Entonces, use el método de base de datos de base64EncodedStringWithOptions , empújelo al servidor y luego use datos reversa base64decoded :) Eso es mucho más fácil :)

NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];


Es mi solución y funciona bien en mi aplicación:

NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];

  • convertir NSData a NSString con stringWithFormat
  • recortar el "<>"
  • eliminar los espacios

Esta es una solución un poco más corta:

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


Intenté probar dos métodos diferentes con el formato "%02.2hhx" y "%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)

y el resultado es que el más rápido es "%02x" a un promedio de 2.0 vs 2.6 para la versión reducida:

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


Lanzando mi respuesta en la pila. Evite usar el análisis de cadenas; Los documentos no garantizan que NSData.description siempre funcione de esa manera.

Implementación 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() } }


Para Swift:

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


Para aquellos que quieran en Swift 3 y el método más fácil

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


Podrías usar esto

- (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]; }


Pruebe esto a menos que los datos estén terminados en nulo.

NSString* newStr = [[NSString alloc] initWithData:newDeviceToken encoding:NSUTF8StringEncoding];


Rápido

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


Rápido:

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


Si alguien está buscando una manera de hacer esto en 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)") }

Editar: para Swift 3

Swift 3 introduce el tipo de Data , con semántica de valores. Para convertir deviceToken en una Cadena, puede hacer lo siguiente:

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


Use una excelente categoría!

// archivo .h

@interface NSData (DeviceToken) - (NSString *)stringDeviceToken; @end

// archivo .m

#import "NSData+DeviceToken.h" @implementation NSData (DeviceToken) - (NSString *)stringDeviceToken { const unsigned *deviceTokenBytes = [deviceToken bytes]; NSString *deviceToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x", ntohl(deviceTokenBytes[0]), ntohl(deviceTokenBytes[1]), ntohl(deviceTokenBytes[2]), ntohl(deviceTokenBytes[3]), ntohl(deviceTokenBytes[4]), ntohl(deviceTokenBytes[5]), ntohl(deviceTokenBytes[6]), ntohl(deviceTokenBytes[7])]; return deviceToken; }

@fin

// AppDelegate.m

#import "NSData+DeviceToken.h" - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString *token = deviceToken.stringDeviceToken; }

¡Funciona bien!


utilizar esta :

NSString * deviceTokenString = [[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""] stringByReplacingOccurrencesOfString: @" " withString: @""]; NSLog(@"The generated device token string is : %@",deviceTokenString);


Swift 3:

Si alguien está buscando una forma de obtener el token del dispositivo en Swift 3. Utilice el fragmento modificado a continuación.

let characterSet: CharacterSet = CharacterSet( charactersIn: "<>" ) let deviceTokenString: String = (deviceToken.description as NSString) .trimmingCharacters(in: characterSet as CharacterSet) .replacingOccurrences(of: " ", with: "") .uppercased() print(deviceTokenString)


-(NSString *)deviceTokenWithData:(NSData *)data { NSString *deviceToken = [[data description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; deviceToken = [deviceToken stringByReplacingOccurrencesOfString:@" " withString:@""]; return deviceToken; }


NSString *tokenString = [[newDeviceToken description] stringByReplacingOccurrencesOfString:@"[<> ]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [[newDeviceToken description] length])];


NSString *tokenstring = [[NSString alloc] initWithData:token encoding:NSUTF8StringEncoding];


var token: String = "" for i in 0..<deviceToken.count { token += String(format: "%02.2hhx", deviceToken[i] as CVarArg) } print(token)