Cesare
Cesare

Reputation: 9419

How to convert an Int into NSData in Swift?

In Objective-C I use the following code to

  1. Convert an Int variable into NSData, a packet of bytes.

    int myScore = 0;
    NSData *packet = [NSData dataWithBytes:&myScore length:sizeof(myScore)];
    
  2. 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

Answers (7)

Vyacheslav
Vyacheslav

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

jamal zare
jamal zare

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

Brody Robertson
Brody Robertson

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

dengST30
dengST30

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

Rob
Rob

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

Raphael
Raphael

Reputation: 10549

With Swift 3.x to 5.0:

var myInt = 77
var myIntData = Data(bytes: &myInt, 
                     count: MemoryLayout.size(ofValue: myInt))

Upvotes: 70

David V
David V

Reputation: 2144

You can convert in this way:

var myScore: NSInteger = 0
let data = NSData(bytes: &myScore, length: sizeof(NSInteger))

Upvotes: 4

Related Questions