如何将我的设备令牌(NSData)转换为NSString?

我正在实施推送通知。 我想将我的APNS令牌保存为一个string。

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

代码的第一行输出null。 第二个打印令牌。 我怎样才能得到我的newDeviceToken作为一个NSString?

用这个 :

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

如果有人正在寻找一种方法在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

Swift 3引入了Datatypes和值语义。 要将deviceToken转换为string,可以执行如下操作:

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

有人帮助我,我只是路过

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

你可以用这个

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

对于那些想要Swift 3和最简单的方法

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

这是我的解决scheme,它适用于我的应用程序:

  NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""]; 
  • 使用stringWithFormatNSData转换为NSString
  • 修剪“<>”
  • 删除空格

这是一个短一点的解决scheme:

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

functionSwift版本

一个class轮:

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

这里有一个可重复使用和自我logging的扩展forms:

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

或者,使用reduce("", combine: +)而不是joinWithSeparator("")作为您的同行的function主。


编辑:我更改string($ 0,基数:16)为string(格式:“%02x”,$ 0),因为一个数字需要填充零

(我还不知道如何将问题标记为另一个问题的重复,所以我只是再次发布我的答案)

我认为将deviceToken转换为hex字节的string是没有意义的。 为什么? 你会把它发送到你的后端,在那里它将被转换回被推送到APNS的字节。 所以,使用NSData的方法base64EncodedStringWithOptions ,将其推送到服务器,然后使用反向base64解码的数据:)这是太容易了:)

 NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; 

一线解决scheme呢?

目标C

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

迅速

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

对于Swift:

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

把我的答案扔在一堆。 避免使用stringparsing; 文档无法保证NSData.description将始终以这种方式工作。

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

迅速:

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

迅速

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

我试图用格式"%02.2hhx""%02x"来testing两种不同的方法

  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) 

结果是最快的是平均2.0的"%02x"和缩小版本的2.6:

 deviceToken.reduce("", {$0 + String(format: "%02x", $1)}) 
 -(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])]; 

Swift 3:

如果有人正在寻找一种方法来获取设备令牌在Swift 3中使用下面修改后的代码片段。

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

使用优秀的类别!

// .h文件

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

// .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; } 

@结束

// AppDelegate.m

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

工作正常!

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

尝试这一个,除非数据是空终止的。

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

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