2014-11-05 42 views
1

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

我知道我可以直接从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) 
+0

明白,几乎没有人知道GATT暗示什么样的数据结构。但是你显然想要做的那种反汇编最好在纯C中执行,或者通过定义'struct'来覆盖数据,或者通过读取单个字节并将其组装成所需的形式。 – 2014-11-05 12:18:49

+0

这就是我要来的结论,但我希望有人可能会有不同的答案。读取单个字节在Swift中并不难,它只是单调乏味。 – 2014-11-05 12:40:31

+0

最好的办法就是想出一个标准化的“风格”,用来处理所有事情,而不是特别的。例如,编写实用程序的方法,给你一个'int'或'double'或其他什么,从NSData对象的给定偏移量开始。然后编写那些移动到/从你的内部结构的序列。将复杂的偏移/长度计算保持在最小值,并将它们全部保留在一个点上。 – 2014-11-05 16:27:29

回答

0

我发现了一个相当通用的方法,可能工作是一些情况。

  1. 创建一个Objective-C骑头
  2. 创建的数据结构作为一个Objective-C结构
  3. 导入与所述数据结构转换为所述桥接报头
  4. 假定已经被称为结构中的首标Foo和一个名为rawData的NSData对象:

使用下面的代码来获得强制转换的指针。

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

这不适用于所有情况,不幸的是在我的特殊情况下工作。我发现的具体问题有:

  • Objective-C结构是字对齐的。如果您的结构没有正确对齐到工作边界,那么您的尺寸可能不正确。 (我在我的特定界面中遇到的问题)
  • 如果您和处理的系统不以您所期望的相同顺序发送数据,那么这将不会处理任何字节顺序转换,但仍然需要完成并且结构可能需要重新排序才能进行补偿。这项工作可能会否定此方法的任何保存。

这是我发现的最简洁的方法,如果它恰好适用于您的特定消息格式。