我有以下类(class):
class RawDataArray {
var data: NSData!
init(filePath: String) {
data = NSData(contentsOfFile: filePath)
}
func read<T>(offset: Int) -> T {
return UnsafePointer<T>(data.bytes + offset).memory
}
}
我在我的 iOS 应用程序中使用它来读取具有自定义格式的二进制文件。例如,要在偏移量 5 处读取 Int
,我使用:
let foo = rawData.read(5) as Int
这可以在我的 iPad Air 模拟器中运行,并且已经通过了 Beta 测试的审查。但是,我的外部测试人员使用的是 iPad 2s 和 4s,他们遇到了 EXC_ARM_DA_ALIGN
错误。
我无法更改输入文件的结构。有什么方法可以修复 read
函数以确保对象是从正确对齐的内存位置构建的?
最佳答案
是的,读取未对齐的数据在某些架构上可能会失败。 一种安全的方法是将字节复制到一个(正确对齐的)变量中。
所以第一个想法是编写一个通用函数:
func read<T>(offset: Int) -> T {
var value : T
memcpy(&value, data.bytes + offset, UInt(sizeof(T)))
return value
}
但是,这不会编译,因为变量 value
使用前必须初始化,没有默认值
可用于初始化完整泛型的构造函数
变量。
如果我们将方法限制为可以用 0
初始化的类型,那么我们会得到:
func read<T : IntegerLiteralConvertible>(offset: Int) -> T {
var value : T = 0
memcpy(&value, data.bytes + offset, UInt(sizeof(T)))
return value
}
这适用于所有整数和浮点类型。
对于一般情况,可以使用 https://stackoverflow.com/a/24335355/1187415 中的想法:
func read<T>(offset: Int) -> T {
// Allocate space:
let ptr = UnsafeMutablePointer<T>.alloc(1)
// Copy data:
memcpy(ptr, data.bytes + offset, UInt(sizeof(T)))
// Retrieve the value as a new variable:
var item = ptr.move()
// Free the allocated space
ptr.dealloc(1)
return item
}
Swift 允许重载具有不同返回类型的函数, 因此你实际上可以定义两个方法,编译器会 自动选择限制性更强的一个。
关于ios - 在 Swift 中从 NSData 读取时的 EXC_ARM_DA_ALIGN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28507412/