Brandon Brandon - 2 months ago 13
Swift Question

Swift NSMutableData append Byte

I'm trying to append one byte to an NSMutable data variable in swift and I'm looking for an easier way. The relevant objective-c code would be:

NSMutableData *data = [[NSMutableData alloc] init];
uint8_t number = 255;
[data appendBytes:&number length:2];


I haven't found that I can do something similar in Swift. What does work is to first create an array of Byte values and then pass that in. For example:

var data = NSMutableData()
let value: Byte = 0xFF
let byte: [Byte] = [value]
data.appendBytes(byte, length: 1)

//this works too and is a little simpler
data.appendBytes([value] as [Byte], length: 1)


Is there a simpler way or am I missing something? The doc specifies that it needs an UnsafePointer and an UnsafePointer can be created with a Word (typealias for Int), so the following works

var word: Word = 255
data.appendBytes(UnsafePointer(bitPattern: word), length: 4)


But that's not really what I want - I want a Byte (UInt8). Any suggestions?

Answer

According to Using Swift with Cocoa and Objective-C, when a function is declared as taking a UnsafePointer argument, it can accept any of the following:

  • nil, which is passed as a null pointer

  • An UnsafePointer, UnsafeMutablePointer, or AutoreleasingUnsafeMutablePointer value, which is converted to UnsafePointer if necessary

  • An in-out expression whose operand is an lvalue of type Type, which is passed as the address of the lvalue

  • A [Type] value, which is passed as a pointer to the start of the array, and lifetime-extended for the duration of the call

The third bullet means you can do:

var value: Byte = 0xFF    // must be var, let will not work
data.appendBytes(&value, length: 1)

Note: You must use var here and not let because it must be an lvalue.

If you find yourself adding a single byte frequently, you could extend NSMutableData:

extension NSMutableData {
    func appendByte(var b: Byte) {
        self.appendBytes(&b, length: 1)
    }
}

var data = NSMutableData()
data.appendByte(255)

Edit (Swift 3):

extension NSMutableData {
  func appendByte(_ i: Int8) {
    var i = i
    self.append(&i, length: 1)
  }
}

var data = NSMutableData()
data.appendByte(255)