Come tradurre i token push tra le rappresentazioni NSData e NSString in Swift?

Ho usato le seguenti routine Objective C per anni, per convertire un token push NSData in un NSString (per l'uso da un servizio push web side), e l'inverso, per prendere una versione NSString nota del token e ricreare la rappresentazione NSData. Ora, trovo la necessità delle stesse identiche capacità, ma in Swift.

Il codice DataToHex Objective C utilizza essenzialmente la formattazione printf:

- (NSString *)dataToHex:(NSData *)data { NSMutableString *str = [NSMutableString stringWithCapacity:100]; const unsigned char *p = [data bytes]; NSUInteger len = [data length]; for(int i=0; i<len; ++i) { [str appendFormat:@"%02.2X", p[i]]; } return str; } 

La traduzione inversa è:

 - (NSData *)hexToData:(NSString *)str { const char *ptr = [str cStringUsingEncoding:NSASCIIStringEncoding]; NSUInteger len = [str length]/2; NSMutableData *data = [NSMutableData dataWithCapacity:len]; while(len--) { char num[5] = (char[]){ '0', 'x', 0, 0, 0 }; num[2] = *ptr++; num[3] = *ptr++; uint8_t n = (uint8_t)strtol(num, NULL, 0); [data appendBytes:&n length:1]; } return data; } 

Mediante "intelligentemente" la sovrascrittura di un due byte in un arrays ASCII, la string "0xXX" viene convertita in un byte, che viene quindi aggiunto all'object dati mutabile.

Ora che sto codificando in Swift, ho bisogno delle stesse funzionalità ma non ho trovato nessun post con qualcosa come il codice sopra in Swift.

Solutions Collecting From Web of "Come tradurre i token push tra le rappresentazioni NSData e NSString in Swift?"

La conversione dalla rappresentazione NSData fornita da iOS corrisponde al codice Objective C quasi in linea per la row:

 func dataToHex(data: NSData) -> String { var str: String = String() let p = UnsafePointer<UInt8>(data.bytes) let len = data.length for var i=0; i<len; ++i { str += String(format: "%02.2X", p[i]) } return str } 

Tuttavia, dato un object NSString, la conversione su un object NSData è un po 'più difficile. Potrebbe essere necessario eseguire questa operazione se si esegue il test nel simulatore, si dispone di un token di string da un dispositivo reale e è necessario registrarlo con un servizio.

Il primo approccio che ho provato ha cercato di replicare il codice che ho usato prima, creando una string con coppie di caratteri e chiamando strtol :

 func hexToData0(str: NSString) -> NSData { let len = str.length/2 var data = NSMutableData(capacity:len)! var num: [Int8] = [ 0, 0, 0 ] let ptr = str.cStringUsingEncoding(NSUTF8StringEncoding) for var i=0; i<len; ++i { num[0] = ptr[i*2+0] num[1] = ptr[i*2+1] var n = UInt8 ( strtol(&num, nil, 16) ) data.appendBytes(&n, length:1) } return data; } 

Ho appena sentito che lo strtol era un po ' NSScanner , quindi ho fatto lo stesso usando NSScanner per le stesse size del codice, ma molto probabilmente less efficiente:

 func hexToData1(str: NSString) -> NSData { var data = NSMutableData(capacity: str.length/2)! for var i = 0; i<str.length; i+=2 { let r = NSRange(location: i, length: 2) let s = str.substringWithRange(r) let sc = NSScanner(string: s) var val: UInt32 = 0 let ret = sc.scanHexInt(&val) if ret { var b = UInt8(val) data.appendBytes(&b, length: 1) } else { assert(false, "Yikes!") } } return data } 

Poi, mi è venuto in mente che avrei potuto fare tutto in Swift, senza bisogno di Darwin o di Fondazione, a scapito di qualche altra row di codice:

 func hexToData(str: NSString) -> NSData { let len = str.length/2 var data = NSMutableData(capacity:len)! let ptr = str.cStringUsingEncoding(NSUTF8StringEncoding) for var i=0; i<len; ++i { var num: UInt8 = 0 var multi: UInt8 = 16; for var j=0; j<2; ++j { let c: UInt8 = UInt8(ptr[i*2+j]) var offset: UInt8 = 0 switch c { case 48...57: // '0'-'9' offset = 48 case 65...70: // 'A'-'F' offset = 65 - 10 // 10 since 'A' is 10, not 0 case 97...102: // 'a'-'f' offset = 97 - 10 // 10 since 'a' is 10, not 0 default: assert(false) } num += (c - offset)*multi multi = 1 } data.appendBytes(&num, length:1) } return data; } 

Sto usando l' hexToData nel mio codice.