swift - 在for循环中为元组赋值
问题描述
在 struct MIDIPacket 中有一个 UInt8 的元组。正常分配是这样的:
import CoreMIDI
let packet = MIDIPacket()
packet.data.0 = 0x02
packet.data.1 = 0x5f
等等。
这个元组的长度约为 128+。有一个转换后的值数组,我想将其分配给从某个索引开始的数据包。
let converted = [0x01, 0x02, 0x5e,...]
var k = packet starting index of assignment
for i in 0..<converted.count {
packet.data(k) = converted[i]
k += 1
}
我该怎么做呢?下标不起作用:例如packet.data[i]
,虽然我相信 Mirror 只是创建了数据包的副本,所以分配给它是行不通的。
let bytes = Mirror(reflecting: packet.data).children;
for (_, b) in bytes.enumerated() {
}
解决方案
没有用于执行此操作的官方 API,但 IIRC,同质元素类型的元组保证具有连续的内存布局。UnsafeBufferPointer
您可以通过使用来读取/写入元组来利用这一点。
通常这需要您手动对元组的元素计数进行硬编码,但我编写了一些可以为您执行此操作的辅助函数。有两种变体,一个可变的,它可以让您获得一个UnsafeBufferPointer
,您可以阅读(例如创建一个Array
),一个可变的,它为您提供一个UnsafeMutableBufferPointer
,您可以通过它分配元素。
enum Tuple {
static func withUnsafeBufferPointer<Tuple, TupleElement, Result>(
to value: Tuple,
element: TupleElement.Type,
_ body: (UnsafeBufferPointer<TupleElement>) throws -> Result
) rethrows -> Result {
try withUnsafePointer(to: value) { tuplePtr in
let count = MemoryLayout<Tuple>.size / MemoryLayout<TupleElement>.size
return try tuplePtr.withMemoryRebound(
to: TupleElement.self,
capacity: count
) { elementPtr in
try body(UnsafeBufferPointer(start: elementPtr, count: count))
}
}
}
static func withUnsafeMutableBufferPointer<Tuple, TupleElement, Result>(
to value: inout Tuple,
element: TupleElement.Type,
_ body: (UnsafeMutableBufferPointer<TupleElement>) throws -> Result
) rethrows -> Result {
try withUnsafeMutablePointer(to: &value) { tuplePtr in
let count = MemoryLayout<Tuple>.size / MemoryLayout<TupleElement>.size
return try tuplePtr.withMemoryRebound(
to: TupleElement.self,
capacity: count
) { elementPtr in
try body(UnsafeMutableBufferPointer(start: elementPtr, count: count))
}
}
}
}
var destinationTouple: (Int, Int, Int, Int) = (0, 0, 0, 0) // => (0, 0, 0, 0)
var sourceArray = Array(1...4)
print("before:", destinationTouple)
Tuple.withUnsafeMutableBufferPointer(to: &destinationTouple, element: Int.self) { (destBuffer: UnsafeMutableBufferPointer<Int>) -> Void in
sourceArray.withUnsafeMutableBufferPointer { sourceBuffer in
// buffer[...] = 1...
destBuffer[destBuffer.indices] = sourceBuffer[destBuffer.indices]
return ()
}
}
print("after:", destinationTouple) // => (1, 2, 3, 4)
推荐阅读
- c# - 后台线程更新值,在非 UI 线程上调用 OnPropertyChanged,因此出现错误
- php - Codeigniter 3中控制器的问题加载视图
- python - Python 3.x 写入电子表格 - 将数据写入 for 循环中的单元格范围,而不仅仅是两个指定的单元格
- rest - GraphQL API 默认是 RESTful 的吗?
- elasticsearch - Kubernetes 集群与虚拟机上的弹性搜索集群
- kubernetes - 在 Pod(容器)被杀死之前从它获取日志文件?
- android - Android 上的 Detox 构建失败:dexing 时出错
- ios - 维护添加到 KeyWindow 的自定义 UIView
- javascript - 以与 mousedown/mousemove/mouseup 相同的方式处理 touchstart/touchmove/touchend
- python - python中3D numpy数组的体积计算?