从 NSData 创建 ENUM

Create ENUM from NSData

有什么方法可以从 NSData 对象创建 ENUM 吗? 我从蓝牙设备收到一个 NSData,为了让它更具可读性,我想使用 ENUM。

我现在的代码:

let data = NSData(bytes: [0x00, 0x12] as [UInt8], length: 2)

let initData =  NSData(bytes: [0xa2,0x12] as [UInt8], length: 2)
let openedData =  NSData(bytes: [0xa1,0x12] as [UInt8], length: 2)
let alreadyOpenedData =  NSData(bytes: [0xa1,0x13] as [UInt8], length: 2)
let finishedData =  NSData(bytes: [0xa3,0x12] as [UInt8], length: 2)

switch data{
case openedData:
    print("opened")
    break
case alreadyOpenedData:
    print("alreadyOpened")
    break
case initData:
    print("ini")
    break
case finishedData:
    print("finished")
default:
    print("error")
}

您可以这样做,前提是您有一组预定义的消息可能值:

import Foundation

let data = NSData(bytes: [0xa2, 0x12] as [UInt8], length: 2)

enum Data: UInt16 {
  case Init = 0x12a2
  case Opened = 0x12a1
  case AlreadyOpened =  0x13a1
  case Finished =  0x12a3
}

func convert(data: NSData) -> UInt16? {
  guard data.length == 2 else { return nil } // with thanks to Rob Napier
  return UnsafePointer<UInt16>(data.bytes).memory
}

if let convertedValue = convert(data),
   let convertedData = Data(rawValue: convertedValue) {
  switch convertedData {
  case .Opened:
    print("opened")
  case .AlreadyOpened:
    print("alreadyOpened")
  case .Init:
    print("ini")
  case .Finished:
    print("finished")
  }
}

假设您所有的代码都是 2 个字节,那么它们可以编码为 UInt16,这很容易原始转换。您只需要做一些数学运算即可将 NSData 转换为 UInt16.

enum State: UInt16 {
    case Init = 0xa212
    case Opened = 0xa112
    case AlreadyOpened = 0xa113
    case Finished = 0xa312

    init?(data: NSData) {
        guard data.length == 2 else { return nil }
        let bytes = UnsafePointer<UInt8>(data.bytes)
        let rawValue = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
        self.init(rawValue: rawValue)
    }
}

if let state = State(data: data) {
    switch state {
    case .Opened:
        print("opened")
        break
    case .AlreadyOpened:
        print("alreadyOpened")
        break
    case .Init:
        print("ini")
        break
    case .Finished:
        print("finished")
    }
} else {
        print("error")
}

(正如 Kenneth Bruno 指出的那样,您也可以在此处使用 UnsafePointer<UInt16> 而不是手动计算。那样会很好;甚至可能更好。)