[英]How to translate push tokens between NSData and NSString representations in Swift?
我已经使用了以下Objective C例程多年,将NSData推送令牌转换为NSString(供Web侧推送服务使用),反之,获取令牌的已知NSString版本并重新创建NSData表示。 现在,我发现需要完全相同的功能,但在Swift中。
dataToHex Objective C代码主要使用printf格式:
- (NSString *)dataToHex:(NSData *)data
{
NSMutableString *str = [NSMutableString stringWithCapacity:100];
const unsigned char *p = [data bytes];
NSUInteger len = [data length];
for(int i=0; i<len; ++i) {
[str appendFormat:@"%02.2X", p[i]];
}
return str;
}
逆向翻译是:
- (NSData *)hexToData:(NSString *)str
{
const char *ptr = [str cStringUsingEncoding:NSASCIIStringEncoding];
NSUInteger len = [str length]/2;
NSMutableData *data = [NSMutableData dataWithCapacity:len];
while(len--) {
char num[5] = (char[]){ '0', 'x', 0, 0, 0 };
num[2] = *ptr++;
num[3] = *ptr++;
uint8_t n = (uint8_t)strtol(num, NULL, 0);
[data appendBytes:&n length:1];
}
return data;
}
通过“巧妙地”覆盖ASCII数组中的两个字节,“0xXX”字符串将转换为一个字节,然后将其附加到可变数据对象。
既然我在Swift编码,我需要相同的功能,但没有发现任何类似Swift上面代码的帖子。
从iOS提供的NSData表示转换匹配Objective C代码几乎为line:
func dataToHex(data: NSData) -> String
{
var str: String = String()
let p = UnsafePointer<UInt8>(data.bytes)
let len = data.length
for var i=0; i<len; ++i {
str += String(format: "%02.2X", p[i])
}
return str
}
但是,给定一个NSString对象,转换回NSData对象有点困难。 如果您在模拟器中进行测试,从真实设备获得字符串标记,并且需要它来注册服务,则可能需要执行此操作。
我采用的第一种方法试图复制我之前使用的代码,通过创建一个包含字符对的字符串,并调用strtol
:
func hexToData0(str: NSString) -> NSData {
let len = str.length/2
var data = NSMutableData(capacity:len)!
var num: [Int8] = [ 0, 0, 0 ]
let ptr = str.cStringUsingEncoding(NSUTF8StringEncoding)
for var i=0; i<len; ++i {
num[0] = ptr[i*2+0]
num[1] = ptr[i*2+1]
var n = UInt8 ( strtol(&num, nil, 16) )
data.appendBytes(&n, length:1)
}
return data;
}
我只觉得strtol
有点像黑客,所以我使用NSScanner
做了同样的代码大小相同,但效率NSScanner
:
func hexToData1(str: NSString) -> NSData {
var data = NSMutableData(capacity: str.length/2)!
for var i = 0; i<str.length; i+=2 {
let r = NSRange(location: i, length: 2)
let s = str.substringWithRange(r)
let sc = NSScanner(string: s)
var val: UInt32 = 0
let ret = sc.scanHexInt(&val)
if ret {
var b = UInt8(val)
data.appendBytes(&b, length: 1)
} else {
assert(false, "Yikes!")
}
}
return data
}
然后,我想到我可以在Swift中完成所有工作,不需要达尔文或基金会,而代价是更多的代码:
// Swift 4
func hexToData(str: String) -> Data {
let len = str.count/2
var data = Data(capacity:len)
let ptr = str.cString(using: String.Encoding.utf8)!
for i in 0..<len {
var num: UInt8 = 0
var multi: UInt8 = 16;
for j in 0..<2 {
let c: UInt8 = UInt8(ptr[i*2+j])
var offset: UInt8 = 0
switch c {
case 48...57: // '0'-'9'
offset = 48
case 65...70: // 'A'-'F'
offset = 65 - 10 // 10 since 'A' is 10, not 0
case 97...102: // 'a'-'f'
offset = 97 - 10 // 10 since 'a' is 10, not 0
default:
assert(false)
}
num += (c - offset)*multi
multi = 1
}
data.append(num)
}
return data;
}
我在我的代码中使用了最终的hexToData
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.