Using Structs (Bytes) with SWIFT – Struct to NSData and NSData to Struct

I’m trying to understand how structs work within SWIFT. I’m familiar with how .NET handles them and how it packs bytes into a structure, etc.

I’m finding some weirdness with the following code:

  • Decode MP3 File from NSData
  • convert UIImage to NSData
  • Objective-C: Getting PNG Thumbnail from Movie with NSData
  • NSData writeToFile:atomically: doesn't immediately save the file
  • Iterate over static properties of a struct
  • Get the data from NSURLSession DownloadTaskWithRequest from completion handler
  • struct exampleStruct {
        var ModelNumber: Byte!
        var MajorVersion: Byte!
        var MinorVersion: Byte!
        var Revision: Byte!
    }
    
    
    var myStruct = exampleStruct (
        ModelNumber: 1,
        MajorVersion: 2,
        MinorVersion: 3,
        Revision: 4
    )
    
    myStruct.MinorVersion  // << Returns  3
    
    // Struct to NSData.
    var data = NSData(
        bytes: &myStruct,
        length: sizeof(exampleStruct)
    )
    
    println("data: \(data)")
    

    The println returns: “data: <01000200 03000400>”

    I was expecting the data to actually be: “data: <01020304>”

    Any idea why SWIFT is not packing 1 byte as 1 byte, instead it’s packing a byte as 2 bytes (1 byte the value and 1 byte as 00)?

    On the flip side if I do the following:

    var newStruct   = exampleStruct(ModelNumber: nil, MajorVersion: nil, MinorVersion: nil, Revision: nil)
    
    var sendBytes:[Byte] = [0x1, 0x2, 0x3, 0x4]
    var newData = NSData(bytes: sendBytes, length: sendBytes.count)
    
    newData.getBytes(
        &newStruct,
        length: sizeof(exampleStruct)
    )
    
    newStruct.MinorVersion // << Returns nil
    
    println(newData)
    

    The println(newData) is correct and what I expect in value: <01020304>

    However, when I access the minorVersion it returns nil, not what I expected as 3.

    Is there a way to force the structure to respect the packing of a byte?

    Solutions Collect From Internet About “Using Structs (Bytes) with SWIFT – Struct to NSData and NSData to Struct”

    Change Byte! to Byte.

    Otherwise you are creating struct holding Optional<Byte> which is larger than one byte because in addition to hold a byte, it need extra byte to indicate if it is nil

    Note: This may still not working as you may need something like __attribute__((packed)) to tell compiler how to deal with alignment. AFAIK, it is not available in Swift.