将NSData字节转换为自定义对象

时间:2014-11-05 12:12:34

标签: ios swift nsdata

我正在开始一个项目来创建一个iOS应用程序,通过BLE与设备进行通信。作为一项新的努力,我试图做到这一点,如果可能的话,Swift。该接口使用GATT和一组现有的自定义消息结构。我得到了NSData对象中来自BLE的数据。我想以相当通用的方式将其转换或直接转换为我的消息结构。

我知道我可以直接从NSData对象的字节数组或使用NSInputStream手动提取数据。虽然这有效,但它可能是一个维护问题,并且界面中有许多不同的消息。

有更简单的方法吗?

我愿意在Objective-C中创建消息结构并在那里进行转换,但是我对Objective-C的了解并不比我对Swift的知识好多了。

我在游乐场玩的一些示例代码如下所示。这一切都按预期工作。

func getBytesFromNSData(data: NSData, start: Int) -> [UInt8] {
    let count = data.length / sizeof(UInt8)
    let remaining = count - start
    let range = NSMakeRange(start, remaining )
    var dataArray = [UInt8](count: remaining, repeatedValue: 0)
    data.getBytes(&dataArray, range: range)
    return dataArray
}

class TestObject {
    var a: Byte
    var b: Byte

    init() {
        a = 0x01
        b = 0x02
    }

    init(data: NSData) {
        let dataBytes = getBytesFromNSData(data, 0)
        a = Byte(dataBytes[0])
        b = Byte(dataBytes[1])
    }

    func populateFromStream(data: NSData) {
        var stream = NSInputStream(data: data)
        stream.open()
        var bytesRead = stream.read(&a, maxLength: 1)
        println("\(bytesRead)")

        bytesRead = stream.read(&b, maxLength: 1)
        println("\(bytesRead)")
    }

    func toArray() -> [Byte] {
        var result = [Byte](count: 2, repeatedValue: 0)
        result[0] = a
        result[1] = b

        return result
    }
}

let test = TestObject()
let testArray = test.toArray()
let length = testArray.count
let testData = NSData(bytes: testArray, length: length)
println("\(testData)")

let testIn = [ Byte(0x0d), Byte(0x0e) ]
let testDataIn = NSData(bytes: testIn, length: testIn.count)
println("\(testDataIn)")

let testConstructor = TestObject(data: testDataIn)

var testObject = TestObject()
testObject.populateFromStream(testDataIn)

1 个答案:

答案 0 :(得分:0)

我发现了一种相当通用的方法,可能在某些情况下起作用。

  1. 创建一个Objective-C骑行标题
  2. 将数据结构创建为Objective-C结构
  3. 将带有数据结构的标头导入桥接标题
  4. 假设您有一个名为Foo的结构和一个名为rawData的NSData对象:
  5. 使用以下代码获取强制转换指针。

    let structureSize = sizeof(Foo)
    var myObject = UnsafeMutablePointer<Foo>.alloc(1).memory
    rawData.getbytes(&myObject, length: structureSize)
    

    这不适用于所有情况,不幸的是在我的特定情况下也可以。我发现的具体问题是:

    • Objective-C结构是单词对齐的。如果您的结构未正确对齐工作边界,则可能是大小不正确。 (我在特定界面中碰到的东西)
    • 如果您处理的系统没有按照您期望的顺序发送数据,那么这将无法处理任何字节顺序转换,这仍然需要完成,结构可能需要被重新订购以弥补。这项工作可能会抵消这种方法的任何节省。

    如果碰巧使用您的特定消息格式,这是我发现的最简洁的方法。