How can I convert my device token (NSData) into an NSString?
我正在实现推送通知。我想把我的APN令牌保存为字符串。
1 2 3 4 5 6 7 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken { NSString *tokenString = [NSString stringWithUTF8String:[newDeviceToken bytes]]; //[[NSString alloc]initWithData:newDeviceToken encoding:NSUTF8StringEncoding]; NSLog(@"%@", tokenString); NSLog(@"%@", newDeviceToken); } |
第一行代码打印空值。第二个打印令牌。如何将新设备标记为nsstring?
如果有人正在寻找一种快速完成这项工作的方法:
1 2 3 4 5 6 7 8 9 10 | 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引入了
1 2 3 4 | func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let token = deviceToken.map { String(format:"%02.2hhx", $0) }.joined() print(token) } |
有人帮了我,我只是路过而已
1 2 3 4 5 6 7 8 9 10 | - (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]; } |
你可以用这个
1 2 3 4 5 6 7 8 9 10 | - (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]; } |
使用此:
1 2 3 4 5 6 | NSString * deviceTokenString = [[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""] stringByReplacingOccurrencesOfString: @"" withString: @""]; NSLog(@"The generated device token string is : %@",deviceTokenString); |
对于那些想要快速3和最简单方法的人
1 2 3 4 | func extractTokenFromData(deviceToken:Data) -> String { let token = deviceToken.reduce("", {$0 + String(format:"%02X", $1)}) return token.uppercased(); } |
这是我的解决方案,它在我的应用程序中运行良好:
1 2 | NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@"" withString:@""]; |
- 用
stringWithFormat 将NSData 转换为NSString 。 - 修剪"< >"
- 删除空格
我认为将devicetoken转换为十六进制字节字符串是没有意义的。为什么?您将把它发送到您的后端,在那里它将被转换回要推送到APN的字节。所以,使用nsdata的方法
1 | NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; |
这是一个简短的解决方案:
1 2 3 4 5 | 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])]; |
功能性swift版本
一班轮:
1 2 | let hexString = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes), count: data.length).map { String(format:"%02x", $0) }.joinWithSeparator("") |
以下是一个可重用的自文档扩展表单:
1 2 3 4 5 6 7 8 9 10 11 12 | 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("") } } |
或者,用
编辑:我将字符串($0,基数:16)更改为字符串(格式:"%02X",$0),因为一个数字需要填充零
(我还不知道如何将一个问题标记为另一个问题的副本,所以我再次发布了我的答案)
一条线解决方案怎么样?
目标C
1 | NSString *token = [[data.description componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet]invertedSet]]componentsJoinedByString:@""]; |
迅捷
1 | let token = data.description.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet).joinWithSeparator("") |
Swift:
1 2 3 4 5 6 | var characterSet: NSCharacterSet = NSCharacterSet( charactersInString:"<>" ) var deviceTokenString: String = ( deviceToken.description as NSString ) .stringByTrimmingCharactersInSet( characterSet ) .stringByReplacingOccurrencesOfString("", withString:"" ) as String println( deviceTokenString ) |
高票答卷中对
% :介绍x 转换说明符。02 :转换值的最小宽度为2。如果转换值的字节数小于字段宽度,则应在左侧填充0 。.2 :给出x 转换说明符要显示的最小位数。hh :指定x 转换说明符应用于有符号char或无符号char参数(参数将根据整数提升进行提升,但其值在打印前应转换为有符号char或无符号char)。x :无符号参数转换为无符号十六进制格式,格式为"dddd";使用字母"abcdef"。精度规定了要显示的最小位数;如果要转换的值可以用较少的位数表示,则应使用前导零进行扩展。默认精度为1。明确精度为零的零转换结果不应为字符。
有关详细信息,请参阅IEEE printf规范。
基于以上的解释,我认为最好把
对于Swift 5,以下方法都是可行的:
1 | deviceToken.map({String(format:"%02x", $0)}).joined() |
1 | deviceToken.map({String(format:"%.2x", $0)}).joined() |
1 | deviceToken.reduce("", {$0 + String(format:"%02x", $1)}) |
1 | deviceToken.reduce("", {$0 + String(format:"%.2x", $1)}) |
试验如下:
1 2 3 4 | let deviceToken = (0..<32).reduce(Data(), {$0 + [$1]}) print(deviceToken.reduce("", {$0 + String(format:"%.2x", $1)})) // Print content: // 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f |
我试过用格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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) |
其结果是,最快的是
1 | deviceToken.reduce("", {$0 + String(format:"%02x", $1)}) |
把我的答案扔到一叠纸上。避免使用字符串分析;文档不保证nsdata.description总是这样工作。
Swift 3实施:
1 2 3 4 5 6 7 8 9 10 | 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() } } |
Swift:
1 | let tokenString = deviceToken.description.stringByReplacingOccurrencesOfString("[ <>]", withString:"", options: .RegularExpressionSearch, range: nil) |
以下是在xamarin.ios中的操作方法
1 2 3 4 5 | 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 } |
迅捷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 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)") } |
1 2 3 4 5 6 | -(NSString *)deviceTokenWithData:(NSData *)data { NSString *deviceToken = [[data description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; deviceToken = [deviceToken stringByReplacingOccurrencesOfString:@"" withString:@""]; return deviceToken; } |
斯威夫特3:
如果有人想在Swift 3中获取设备令牌。使用下面修改的代码段。
1 2 3 4 5 6 7 8 | let characterSet: CharacterSet = CharacterSet( charactersIn:"<>" ) let deviceTokenString: String = (deviceToken.description as NSString) .trimmingCharacters(in: characterSet as CharacterSet) .replacingOccurrences(of:"", with:"") .uppercased() print(deviceTokenString) |
1 | NSString *tokenString = [[newDeviceToken description] stringByReplacingOccurrencesOfString:@"[<> ]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [[newDeviceToken description] length])]; |
使用优秀的类别!
//h文件
1 2 3 4 5 | @interface NSData (DeviceToken) - (NSString *)stringDeviceToken; @end |
//m文件
1 2 3 4 5 6 7 8 9 10 11 12 | #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; } |
@结束
//应用委托.m
1 2 3 4 5 6 | #import"NSData+DeviceToken.h" - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString *token = deviceToken.stringDeviceToken; } |
工作很好!
1 2 3 4 5 6 | var token: String ="" for i in 0..<deviceToken.count { token += String(format:"%02.2hhx", deviceToken[i] as CVarArg) } print(token) |
请尝试此操作,除非数据以NULL结尾。
encoding:NSUTF8StringEncoding];
1 | NSString *tokenstring = [[NSString alloc] initWithData:token encoding:NSUTF8StringEncoding]; |