例えばファイルから読み込んだデータの3バイト目からUInt16を取り出したい場合などに利用します。
本来であれば
let amount: UInt16 = data.getValue(offset: 3)
という感じで呼び出せるようにしたかったのですが、NSDataのgetBytes()を利用するにあたってgetBytes()に渡す変数を初期化しなければならず、その初期化方法がわからなかったため、初期化用の数値を引数で渡さなければいけないという汚いコードになってしまいました。
let amount: UInt16 = data.getValue(offset: 3, initialValue: 0)
以下、Dataの拡張宣言によりgetValue()を追加しています。
extension Data {
func getValue<T>(offset: Int, initialValue: T) -> T? {
var data: T = initialValue
let itemSize = MemoryLayout.size(ofValue: data)
let maxOffset = count - itemSize
guard Range(0...maxOffset).contains(offset) else {
return nil
}
let nsdata = self as NSData
nsdata.getBytes(&data, range: NSMakeRange(offset, itemSize))
return data
}
}
使い方
let data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
let value16: UInt16? = data.getValue(offset: 1, initialValue: 0)
if let val = value16 {
debugPrint(String(format: "value=0x%x", val))
} else {
debugPrint("value is nil")
}
let value32: UInt32? = data.getValue(offset: 1, initialValue: 0)
if let val = value32 {
debugPrint(String(format: "value=0x%x", val))
} else {
debugPrint("value is nil")
}
initialValueを使わなくてもいい方法があれば教えてください!