Reputation: 9419
In Objective-C I use the following code to
Convert an Int
variable into NSData
, a packet of bytes.
int myScore = 0;
NSData *packet = [NSData dataWithBytes:&myScore length:sizeof(myScore)];
Use the converted NSData
variable into a method.
[match sendDataToAllPlayers:
packet withDataMode: GKMatchSendDataUnreliable
error: &error];
I tried converting the Objective-C code into Swift:
var myScore : Int = 0
func sendDataToAllPlayers(packet: Int!,
withDataMode mode: GKMatchSendDataMode,
error: NSErrorPointer) -> Bool {
return true
}
However, I am not able to convert an Int
variable into an NSData
and use it an a method. How can I do that?
Upvotes: 40
Views: 41394
Reputation: 27211
For any integer type:
extension FixedWidthInteger {
var data: Data {
let data = withUnsafeBytes(of: self) { Data($0) }
return data
}
}
Example:
let data = 1.data
Upvotes: 5
Reputation: 1199
Use this initializer to convert every Array to Data
Data(element: Sequence)
example:
let myArr = [12,45,67,898, 100]
let myArrData = Data(myArr)
Upvotes: 0
Reputation: 8604
Depending on the size of Int you are working with, a straight forward approach is to init Data with Sequence of UInt8:
let value: Int = 100
let data = Data([UInt8(value)])
// OR
let data = Data([0xFF, 0xFE])
Upvotes: -1
Reputation: 4037
Swift 5, add an other option.
NSData
is old, still effective
Write Data:
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)
}
})
Read data:
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
}
You know the memory layout, the data put in the memory,
Then put them out exactly.
unsafe
method is funny
Upvotes: 3
Reputation: 437552
In contemporary versions of Swift, I would do:
let score = 1000
let data = withUnsafeBytes(of: score) { Data($0) }
e8 03 00 00 00 00 00 00
And convert that Data
back to an Int
:
let value = data.withUnsafeBytes {
$0.load(as: Int.self)
}
Note, when dealing with binary representations of numbers, especially when exchanging with some remote service/device, you might want to make the endianness explicit, e.g.
let data = withUnsafeBytes(of: score.littleEndian) { Data($0) }
e8 03 00 00 00 00 00 00
And convert that Data
back to an Int
:
let value = data.withUnsafeBytes {
$0.load(as: Int.self).littleEndian
}
Versus big endian format, also known as “network byte order”:
let data = withUnsafeBytes(of: score.bigEndian) { Data($0) }
00 00 00 00 00 00 03 e8
And convert that Data
back to an Int
:
let value = data.withUnsafeBytes {
$0.load(as: Int.self).bigEndian
}
Needless to say, if you don’t want to worry about endianness, you could use some established standard like JSON (or even XML).
For Swift 2 rendition, see previous revision of this answer.
Upvotes: 59
Reputation: 10549
With Swift 3.x to 5.0:
var myInt = 77
var myIntData = Data(bytes: &myInt,
count: MemoryLayout.size(ofValue: myInt))
Upvotes: 70
Reputation: 2144
You can convert in this way:
var myScore: NSInteger = 0
let data = NSData(bytes: &myScore, length: sizeof(NSInteger))
Upvotes: 4