如何在 Swift 中将 Int 转换为 NSData?
How to convert an Int into NSData in Swift?
在Objective-C我用下面的代码来
将一个Int
变量转换为NSData
,一个字节包。
int myScore = 0;
NSData *packet = [NSData dataWithBytes:&myScore length:sizeof(myScore)];
将转换后的NSData
变量用到方法中。
[match sendDataToAllPlayers:
packet withDataMode: GKMatchSendDataUnreliable
error: &error];
我尝试将 Objective-C 代码转换为 Swift:
var myScore : Int = 0
func sendDataToAllPlayers(packet: Int!,
withDataMode mode: GKMatchSendDataMode,
error: NSErrorPointer) -> Bool {
return true
}
但是,我无法将 Int
变量转换为 NSData
并将其用作一种方法。我该怎么做?
您可以这样转换:
var myScore: NSInteger = 0
let data = NSData(bytes: &myScore, length: sizeof(NSInteger))
在现代版本的 Swift 中,我会这样做:
let score = 1000
let data = withUnsafeBytes(of: score) { Data([=10=]) }
e8 03 00 00 00 00 00 00
并将 Data
转换回 Int
:
let value = data.withUnsafeBytes {
[=12=].load(as: Int.self)
}
请注意,在处理数字的二进制表示时,尤其是在与某些远程 service/device 交换时,您可能希望将 endianness 显式化,例如
let data = withUnsafeBytes(of: score.littleEndian) { Data([=13=]) }
e8 03 00 00 00 00 00 00
并将 Data
转换回 Int
:
let value = data.withUnsafeBytes {
[=15=].load(as: Int.self).littleEndian
}
与大端格式,也称为“网络字节序”:
let data = withUnsafeBytes(of: score.bigEndian) { Data([=16=]) }
00 00 00 00 00 00 03 e8
并将 Data
转换回 Int
:
let value = data.withUnsafeBytes {
[=18=].load(as: Int.self).bigEndian
}
不用说,如果你不想担心字节顺序,你可以使用一些既定的标准,比如 JSON(甚至 XML)。
对于 Swift 2 版本,请参阅 previous revision of this answer。
与 Swift 3.x 到 5.0:
var myInt = 77
var myIntData = Data(bytes: &myInt,
count: MemoryLayout.size(ofValue: myInt))
Swift 5, 再加一个选项.
NSData
老了,还有效
写入数据:
let buffer = NSMutableData()
let size = MemoryLayout<UInt>.size
let big = 1000
let small = 10
withUnsafeBytes(of: big, { (p) in
let bufferPointer = p.bindMemory(to: UInt.self)
if let address = bufferPointer.baseAddress{
buffer.append(address, length: size)
}
})
withUnsafeBytes(of: small, { (p) in
let bufferPointer = p.bindMemory(to: UInt.self)
if let address = bufferPointer.baseAddress{
buffer.append(address, length: size)
}
})
读取数据:
if let d = buffer.copy() as? Data{
var big: UInt = 0
var small: UInt = 0
let size = MemoryLayout<UInt>.size
let meta = NSData(data: data)
meta.getBytes(&big, range: NSRange(location: 0, length: size))
meta.getBytes(&small, range: NSRange(location: size, length: size))
print("big:", big, "\nsmall:", small)
// big: 1000
// small: 10
}
你知道内存布局,数据放在内存中,
然后把它们准确地放出来。
unsafe
方法有趣
根据您正在使用的 Int 的大小,一种直接的方法是使用 UInt8 序列初始化数据:
let value: Int = 100
let data = Data([UInt8(value)])
// OR
let data = Data([0xFF, 0xFE])
使用此初始化程序将每个数组转换为数据
Data(element: Sequence)
示例:
let myArr = [12,45,67,898, 100]
let myArrData = Data(myArr)
对于任何整数类型:
extension FixedWidthInteger {
var data: Data {
let data = withUnsafeBytes(of: self) { Data([=10=]) }
return data
}
}
示例:
let data = 1.data
在Objective-C我用下面的代码来
将一个
Int
变量转换为NSData
,一个字节包。int myScore = 0; NSData *packet = [NSData dataWithBytes:&myScore length:sizeof(myScore)];
将转换后的
NSData
变量用到方法中。[match sendDataToAllPlayers: packet withDataMode: GKMatchSendDataUnreliable error: &error];
我尝试将 Objective-C 代码转换为 Swift:
var myScore : Int = 0
func sendDataToAllPlayers(packet: Int!,
withDataMode mode: GKMatchSendDataMode,
error: NSErrorPointer) -> Bool {
return true
}
但是,我无法将 Int
变量转换为 NSData
并将其用作一种方法。我该怎么做?
您可以这样转换:
var myScore: NSInteger = 0
let data = NSData(bytes: &myScore, length: sizeof(NSInteger))
在现代版本的 Swift 中,我会这样做:
let score = 1000
let data = withUnsafeBytes(of: score) { Data([=10=]) }
e8 03 00 00 00 00 00 00
并将 Data
转换回 Int
:
let value = data.withUnsafeBytes {
[=12=].load(as: Int.self)
}
请注意,在处理数字的二进制表示时,尤其是在与某些远程 service/device 交换时,您可能希望将 endianness 显式化,例如
let data = withUnsafeBytes(of: score.littleEndian) { Data([=13=]) }
e8 03 00 00 00 00 00 00
并将 Data
转换回 Int
:
let value = data.withUnsafeBytes {
[=15=].load(as: Int.self).littleEndian
}
与大端格式,也称为“网络字节序”:
let data = withUnsafeBytes(of: score.bigEndian) { Data([=16=]) }
00 00 00 00 00 00 03 e8
并将 Data
转换回 Int
:
let value = data.withUnsafeBytes {
[=18=].load(as: Int.self).bigEndian
}
不用说,如果你不想担心字节顺序,你可以使用一些既定的标准,比如 JSON(甚至 XML)。
对于 Swift 2 版本,请参阅 previous revision of this answer。
与 Swift 3.x 到 5.0:
var myInt = 77
var myIntData = Data(bytes: &myInt,
count: MemoryLayout.size(ofValue: myInt))
Swift 5, 再加一个选项.
NSData
老了,还有效
写入数据:
let buffer = NSMutableData()
let size = MemoryLayout<UInt>.size
let big = 1000
let small = 10
withUnsafeBytes(of: big, { (p) in
let bufferPointer = p.bindMemory(to: UInt.self)
if let address = bufferPointer.baseAddress{
buffer.append(address, length: size)
}
})
withUnsafeBytes(of: small, { (p) in
let bufferPointer = p.bindMemory(to: UInt.self)
if let address = bufferPointer.baseAddress{
buffer.append(address, length: size)
}
})
读取数据:
if let d = buffer.copy() as? Data{
var big: UInt = 0
var small: UInt = 0
let size = MemoryLayout<UInt>.size
let meta = NSData(data: data)
meta.getBytes(&big, range: NSRange(location: 0, length: size))
meta.getBytes(&small, range: NSRange(location: size, length: size))
print("big:", big, "\nsmall:", small)
// big: 1000
// small: 10
}
你知道内存布局,数据放在内存中,
然后把它们准确地放出来。
unsafe
方法有趣
根据您正在使用的 Int 的大小,一种直接的方法是使用 UInt8 序列初始化数据:
let value: Int = 100
let data = Data([UInt8(value)])
// OR
let data = Data([0xFF, 0xFE])
使用此初始化程序将每个数组转换为数据
Data(element: Sequence)
示例:
let myArr = [12,45,67,898, 100]
let myArrData = Data(myArr)
对于任何整数类型:
extension FixedWidthInteger {
var data: Data {
let data = withUnsafeBytes(of: self) { Data([=10=]) }
return data
}
}
示例:
let data = 1.data