How can I convert my device token (NSData) into an NSString?

匿名 (未验证) 提交于 2019-12-03 02:13:02

问题:

I am implementing push notifications. I'd like to save my APNS Token as a String.

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

The first line of code prints null. the second prints the token. How can I get my newDeviceToken as an NSString?

回答1:

use this :

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


回答2:

If anyone is looking for a way to do this in 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)") } 

Edit: For Swift 3

Swift 3 introduces the Data type, with value semantics. To convert the deviceToken to a String, you can do as follows:

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


回答3:

Someone Helped me with this.I am just passing along

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


回答4:

You could use this

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


回答5:

For those who want in Swift 3 and most easier method

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


回答6:

It's my solution and It works well in my app:

    NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken]  stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""]; 
  • convert NSData to NSString with stringWithFormat
  • trim the "<>"
  • remove the spaces


回答7:

This is a little bit shorter solution:

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


回答8:

Functional Swift version

One liner:

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

Here's in a reusable and self documenting extension form:

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

Alternatively, use reduce("", combine: +) instead of joinWithSeparator("") to be seen as a functional master by your peers.


Edit: I changed String($0, radix: 16) to String(format: "%02x", $0), because one digit numbers needed to having a padding zero

(I don't know yet how to mark a question as a duplicate of this other one, so I just posted my answer again)



回答9:

I think converting deviceToken to hex byte string has no sense. Why? You will send it to your backend, where it will be transformed back to bytes to be pushed to APNS. So, use NSData's method base64EncodedStringWithOptions, push it to server, and then use reverse base64decoded data :) That is so much easier :)

NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; 


回答10:

What about one line solution?

Objective C

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

Swift

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


回答11:

For Swift :

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


回答12:

Throwing my answer on the pile. Avoid using string parsing; It's not guaranteed by the docs that NSData.description will always work that way.

Swift 3 Implementation:

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


回答13:

Swift:

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


回答14:

Swift

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


回答15:

I've tried to test two different methods with format "%02.2hhx" and "%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) 

and the result is that the fastest is "%02x" at average 2.0 vs 2.6 for the reduced version:

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


回答16:

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


回答17:

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


回答18:

Swift 3:

If any one is looking for a way to get device token in Swift 3. Use the below modified snippet.

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


回答19:

Use excellent category!

// .h file

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

// .m file

#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; } 

@end

// AppDelegate.m

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

Works fine!



回答20:

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


回答21:

Try this one unless the data is null-terminated.

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



回答22:

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


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!