深入解析 Swift Data 的两种子数据获取方式
在 Swift 开发中处理二进制数据时,Data
类型是我们最常用的工具之一。最近在做视频码流解析的时候,使用了data[Range<Index>]
来获取子数据,然后运行程序崩溃了,经排查了解到Swift Data 切片:data.subdata(in:)
和 data[Range<Index>]
有着本质的区别。实践是检验真理的唯一标准,本文将从底层原理到实际应用,深入对比分析两种获取子数据的方式:data.subdata(in:)
和下标data[Range<Index>]
。
1. 方法签名与基本使用
1.1 data.subdata(in:)
let nalUnitData = data.subdata(in: offset..<nextStartCodeIndex)
1.2 范围下标访问
let nalUnitDataSlice = data[offset..<nextStartCodeIndex]
2. 核心差异解析
2.1 返回类型
方法 | 返回类型 | 内存管理 |
---|---|---|
data.subdata(in:) |
Data | 独立拷贝 |
data[Range<Index>] |
Data.SubSequence | 共享内存 |
2.2 内存分配机制
-
subdata(in:)
创建包含目标字节的独立Data
实例,完全脱离原数据生命周期 -
data[Range<Index>]
返回Data.SubSequence
(即Slice<Data>
),具有以下特点: -
共享底层存储缓冲区
-
引用计数增加但不拷贝数据
-
生命周期依赖原
Data
实例
// 内存布局示意图
Original Data: [##############]
subdata: [####] ← 独立内存块
SubSequence: [####] ← 指针引用
2.3 性能对比
操作 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
subdata(in:) |
O(n) | O(n) | 需要长期持有数据的场景 |
data[Range<Index>] |
O(1) | O(1) | 临时处理/短期使用的场景 |