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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9372815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:56:00  来源:igfitidea点击:

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

iosobjective-capple-push-notificationsnsstringnsdata

提问by Sheehan Alam

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

我正在实施推送通知。我想将我的 APNS 令牌保存为字符串。

- (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?

第一行代码打印 null。第二个打印令牌。如何将我的 newDeviceToken 作为 NSString 获取?

采纳答案by kulss

use this :

用这个 :

NSString * deviceTokenString = [[[[deviceToken description]
                         stringByReplacingOccurrencesOfString: @"<" withString: @""] 
                        stringByReplacingOccurrencesOfString: @">" withString: @""] 
                       stringByReplacingOccurrencesOfString: @" " withString: @""];

NSLog(@"The generated device token string is : %@",deviceTokenString);

回答by Sascha

If anyone is looking for a way to do this in Swift:

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

Swift 3 introduces the Datatype, with value semantics. To convert the deviceTokento a String, you can do as follows:

Swift 3 引入了Data具有值语义的类型。要将 转换deviceToken为字符串,您可以执行以下操作:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02.2hhx", 
- (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];
}
) }.joined() print(token) }

回答by Shubhank

Someone Helped me with this.I am just passing along

有人帮我解决这个问题。我只是路过

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

回答by Vlad Polyanskiy

You could use this

你可以用这个

func extractTokenFromData(deviceToken:Data) -> String {
    let token = deviceToken.reduce("", {
    NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] 
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
+ String(format: "%02X", )}) return token.uppercased(); }

回答by Anand

For those who want in Swift 3and most easier method

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

deviceToken.map({String(format: "%02x", 
deviceToken.map({String(format: "%.2x", 
deviceToken.reduce("", {
deviceToken.reduce("", {
let deviceToken = (0..<32).reduce(Data(), {
let deviceTokenString = deviceToken.map { String(format: "%02x", 
// iOS 12
(deviceToken as NSData).description // "<965b251c 6cb1926d e3cb366f dfb16ddd e6b9086a 8a3cac9e 5f857679 376eab7C>"

// iOS 13
(deviceToken as NSData).description // "{length = 32, bytes = 0x965b251c 6cb1926d e3cb366f dfb16ddd ... 5f857679 376eab7c }"
) }.joined()
+ []}) print(deviceToken.reduce("", {
NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
+ String(format: "%.2x", )})) // Print content: // 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ String(format: "%.2x", )})
+ String(format: "%02x", )})
)}).joined()
)}).joined()

回答by Zeb

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

这是我的解决方案,它在我的应用程序中运行良好:

- (NSString *)fetchDeviceToken:(NSData *)deviceToken {
    NSUInteger len = deviceToken.length;
    if (len == 0) {
        return nil;
    }
    const unsigned char *buffer = deviceToken.bytes;
    NSMutableString *hexString  = [NSMutableString stringWithCapacity:(len * 2)];
    for (int i = 0; i < length; ++i) {
        [hexString appendFormat:@"%02x", buffer[i]];
    }
    return [hexString copy];
}
  • convert NSDatato NSStringwith stringWithFormat
  • trim the "<>"
  • remove the spaces
  • 转换NSDataNSStringstringWithFormat
  • 修剪“<>”
  • 删除空格

回答by jqgsninimo

Explanation of %02.2hhxin the high vote answer:

说明%02.2hhx在高投票答案

  • %: Introduces the xconversion specifier.
  • 02: The minimum width of the converted value is 2. If the converted value has fewer bytes than the field width, it shall be padded with 0on the left.
  • .2: Gives the minimum number of digits to appear for the xconversion specifier.
  • hh: Specifies that the xconversion specifier applies to a signed char or unsigned char argument (the argument will have been promoted according to the integer promotions, but its value shall be converted to signed char or unsigned char before printing).
  • x: The unsigned argument shall be converted to unsigned hexadecimal format in the style "dddd"; the letters "abcdef" are used. The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it shall be expanded with leading zeros. The default precision is 1. The result of converting zero with an explicit precision of zero shall be no characters.
  • %:引入x转换说明符。
  • 02:转换值的最小宽度为2。如果转换值的字节数少于字段宽度,则应0在左侧填充。
  • .2:给出x转换说明符出现的最小位数。
  • hh: 指定x转换说明符适用于有符号字符或无符号字符参数(参数将根据整数提升进行提升,但其值应在打印前转换为有符号字符或无符号字符)。
  • x: 无符号参数应转换为“dddd”样式的无符号十六进制格式;使用字母“abcdef”。精度指定出现的最小位数;如果被转换的值可以用更少的数字表示,它应该用前导零扩展。默认精度为 1。使用显式精度零转换零的结果不应是字符。

For more details, see the IEEE printf specification.

有关更多详细信息,请参阅IEEE printf 规范



Based on the above explanation, I think it is better to change %02.2hhxto %02xor %.2x.

基于上面的解释,我认为最好%02.2hhx改为%02x%.2x

For Swift 5, the following methods are all feasible:

对于Swift 5,以下方法都是可行的:

##代码## ##代码## ##代码## ##代码##

The test is as follows:

测试如下:

##代码##

回答by SuryaKantSharma

In iOS 13 descriptionwill break so use this

在 iOS 13 中description会坏掉所以使用这个

##代码##

For clarity, let's break this down and explain each part:

为了清楚起见,让我们分解并解释每个部分:

The map method operates on each element of a sequence. Because Data is a sequence of bytes in Swift, the passed closure is evaluated for each byte in deviceToken. The String(format:) initializer evaluates each byte in the data (represented by the anonymous parameter $0) using the %02x format specifier, to produce a zero-padded, 2-digit hexadecimal representation of the byte / 8-bit integer. After collecting each byte representation created by the map method, joined() concatenates each element into a single string.

map 方法对序列的每个元素进行操作。因为 Data 是 Swift 中的字节序列,所以传递的闭包会针对 deviceToken 中的每个字节进行评估。String(format:) 初始值设定项使用 %02x 格式说明符评估数据中的每个字节(由匿名参数 $0 表示),以生成字节/8 位整数的零填充、2 位十六进制表示。在收集 map 方法创建的每个字节表示之后,joined() 将每个元素连接成一个字符串。

P.S don't use description gives different string in iOS 12 and iOS 13 and not safe as per future scope. Developers shouldn't have relied on a specific format for an object's description.

PS 不要使用描述在 iOS 12 和 iOS 13 中给出不同的字符串,并且根据未来的范围不安全。开发人员不应该依赖特定格式的对象描述。

##代码##

For more information read This.

欲了解更多信息,请阅读本文

回答by Oleg Shanyuk

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 :)

我认为将 deviceToken 转换为十六进制字节字符串没有意义。为什么?您将把它发送到您的后端,在那里它将被转换回字节以推送到 APNS。因此,使用NSData的方法base64EncodedStringWithOptions,将其推送到服务器,然后使用反向 base64decoded 数据:) 这要容易得多:)

##代码##

回答by Vishnu Prakash

In iOS 13 the description will be in different format. Kindly use below code to fetch the device token.

在 iOS 13 中,描述将采用不同的格式。请使用以下代码获取设备令牌。

##代码##