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

187

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

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

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


第二个 NSLog 的输出是什么,即打印 newDeviceToken 的那个? - rob mayoff
请勿重复:https://dev59.com/o3M_5IYBdhLWcg3wmkeu#35730103 - NiñoScript
do NOT use description - Fattie
31个回答

6

2020

以文本形式的令牌(token)...

let tat = deviceToken.map{ data in String(format: "%02.2hhx", data) }.joined()

或者,如果您更喜欢。
let tat2 = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()

(结果相同)


3

函数式Swift版本

一句话概括:

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

这是一个可重用和自我记录扩展形式:
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("")来让你的同行视你为一个函数式大师。


编辑:我将String($0, radix: 16)更改为String(format: "%02x", $0),因为一位数字需要有填充零。

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


没问题,谢谢。 - Hasya

3
这是一个更为简洁的解决方案:
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])];

2

把我的答案加入堆中。避免使用字符串解析;文档不能保证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()
    }
}

2
这对您有帮助,
NSUInteger dataLength = deviceToken.length;
    
const unsigned char *dataBuffer = (const unsigned char *)deviceToken.bytes;
NSMutableString *deviceTokenString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i) {
    [deviceTokenString appendFormat:@"%02x", dataBuffer[i]];
}
    
NSLog(@"The generated device token string is : %@",deviceTokenString);

1
这是在 Xamarin.iOS 中实现的方法。
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
}

我对此很陌生,但看起来在向APNS发送时需要使用十六进制,所以我不确定为什么你建议使用base64... - Yepeekai

1
使用 updateAccumulatingResult 比这里找到的其他方法更有效,因此这是将您的 Data 字节字符串化的最快捷方式:
func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.reduce(into: "") { $0 += String(format: "%.2x", $1) }
    print(token)
}

亚历克斯,那不会是%02.2hhx吗? - Fattie

1

我尝试使用格式"%02.2hhx""%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)

结果是最快的是平均为2.0的"%02x",而缩减版本的平均值为2.6。
deviceToken.reduce("", {$0 + String(format: "%02x", $1)})

0

对于Swift:

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

println( deviceTokenString )

0
2023
let tokenString = deviceToken.reduce("") { $0 + String(format: "%02.2hhx", $1) }

或者:

let tokenString = deviceToken.map { String(format: "%02.2hhx", $0)}.joined()

要了解为什么建议使用格式02.2hhx,您可以阅读这篇关于NSHipster的文章IEEE规范


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接