How to convert an Int into NSData in Swift?

前端 未结 7 1905
陌清茗
陌清茗 2021-02-03 22:37

In Objective-C I use the following code to

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

    int myScore = 0;
    NS         
    
    
            
相关标签:
7条回答
  • 2021-02-03 22:39

    With Swift 3.x to 5.0:

    var myInt = 77
    var myIntData = Data(bytes: &myInt, 
                         count: MemoryLayout.size(ofValue: myInt))
    
    0 讨论(0)
  • 2021-02-03 22:41

    For any integer type:

    extension FixedWidthInteger {
        var data: Data {
            let data = withUnsafeBytes(of: self) { Data($0) }
            return data
        }
    }
    

    Example:

    let data = 1.data
    
    0 讨论(0)
  • 2021-02-03 22:47

    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])
    
    0 讨论(0)
  • 2021-02-03 23:03

    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

    0 讨论(0)
  • 2021-02-03 23:04

    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.

    0 讨论(0)
  • 2021-02-03 23:04

    You can convert in this way:

    var myScore: NSInteger = 0
    let data = NSData(bytes: &myScore, length: sizeof(NSInteger))
    
    0 讨论(0)
提交回复
热议问题