【问题标题】:Iphone device token - NSData or NSStringIphone 设备令牌 - NSData 或 NSString
【发布时间】:2010-12-07 22:16:24
【问题描述】:

我收到NSData 对象形式的iPhone 设备令牌。 当我测试我的通知脚本功能时,我只从日志中复制了该对象并且通知运行良好。但是,当我现在尝试自动执行此操作时,我将设备令牌作为 ASCII 编码字符串以变量的形式发送

self.deviceToken = [[NSString alloc] initWithData:webDeviceToken encoding:NSASCIIStringEncoding];

我得到的字符串有一些时髦的字符,看起来类似于"å-0¾fZÿ÷ʺÎUQüRáqEªfÔk«"

当服务器端脚本向该令牌发送通知时,我没有收到任何内容。

我需要解码一些东西吗?如何解码?

问候

【问题讨论】:

  • 我在这里找到了另一个解决方案,看起来比“描述”方法更具前瞻性。 stackoverflow.com/questions/1959600/…
  • 这很奇怪,我认为这个 NSData* 不应该是特殊的对象,所以我尝试使用 NSUTF8StringEncoding 并得到不同的结果。用 description 方法将 NSData 转换为 NSString 对我来说是不可想象的!一些与苹果相关的文档?

标签: iphone device-driver token


【解决方案1】:

好的,我找到了解决方案。如果有人有同样的问题,忘记 ASCII 编码,只需使用以下行制作字符串:

NSString *deviceToken = [[webDeviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
deviceToken = [deviceToken stringByReplacingOccurrencesOfString:@" " withString:@""];

【讨论】:

  • 请停止投票这个答案,这使用令牌 .description - 这就是描述。它旨在供人类阅读以进行调试或显示。 “”不是标记的一部分,它们只是用于显示格式。如果他们愿意,Apple 可以在未来将其更改为“[”或“-”或其他任何内容。请改用将数据转换为十六进制字符串的答案之一。
【解决方案2】:

如果有人正在寻找在 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 引入了 Data 类型,具有值语义。要将deviceToken 转换为字符串,您可以执行以下操作:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

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

    print(token)
}

【讨论】:

  • 谢谢!正是我需要的!
  • 令人惊讶的是,没有简单的方法可以快速从 NSData 设备令牌对象中获取适当解码的字符串数据。但这是来自@sascha 的示例,这是我遇到的第一个真正有效的东西!谢谢。
  • 现在将其移至 NSData 扩展并命名为 hexadecimalStringDescription()
【解决方案3】:

我发现这个解决方案更好,因为 iOS 可以在未来的版本中改变描述的使用,所以在数据上使用描述属性在未来可能是不可靠的。 我们可以通过从数据令牌字节创建十六进制令牌来直接使用它。

 - (void)application:(UIApplication *)app 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];

}

我们还可以将设备令牌存储在我们的 NSUserdefaults 中,稍后使用它发送到我们的服务器。

【讨论】:

    【解决方案4】:

    我认为这不是一个好的解决方案,因为您必须在将通知发送到 Apple 服务器之前重构字符串。使用 Base64 编码来传输字符串或类似的东西。

    【讨论】:

    • 发送的字符串从服务器端工作,无需任何重构或修改
    • 但据我所知,您正在删除和修剪字符......您是否尝试使用该令牌发送通知并且它有效?怎么会?
    【解决方案5】:

    另一种将设备令牌转换为十六进制字符串的方法

    NSUInteger capacity = [deviceToken length] * 2;
    NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:capacity];
    const unsigned char *dataBuffer = [deviceToken bytes];
    NSInteger i;
    for (i=0; i<[deviceToken length]; ++i) {
        [stringBuffer appendFormat:@"%02X", (NSUInteger)dataBuffer[i]];
    }
    NSLog(@"token string buffer is %@",stringBuffer);
    

    【讨论】:

      【解决方案6】:

      对于 Swift 3:

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

      其他方法

      为获取十六进制字符串创建数据扩展

      extension Data {
          var hexString: String {
              return map { String(format: "%02.2hhx", arguments: [$0]) }.joined()
          }
      }
      

      并在

      中调用这个扩展
      func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
          let tokenString = deviceToken.hexString()
          print("token: \(tokenString)")
      }
      

      【讨论】:

      • 不要依赖 .description,您从中获得的格式是未记录的,并且在技术上可能会发生变化。 deviceToken.description 只能用于调试目的。改用将字节转换为十六进制字符串的答案之一。
      • 同意。不要使用这个。使用 PKPushCredentials 时,描述现在返回“32 字节”
      猜你喜欢
      • 2012-03-11
      • 2015-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多