问题描述
我从我正在开发的应用程序中获得了此代码。当 BLE 人员离开团队时,我继承了此代码。我不擅长低级的东西和数据的东西。我是 UI/UX 前端人员,现在我确实需要亲自动手。这段代码现在有点旧并且使用了不推荐使用的代码。我一直试图使警告静音,但没有成功,但我一直以相同的代码或错误告终。
这是生成警告的代码。使用 withUnsafeBytes 时的返回行
extension Data {
func scanValueFromData<T>(start: Int = 0,invalid: T) -> (T,Int) {
let length = MemoryLayout<T>.size
guard self.count >= start + length else {
return (invalid,start+length)
}
return (self.subdata(in: start..<start+length).withUnsafeBytes{ $0.pointee },start+length)
}
}
此方法用于将字节数组解码为结构体。我从 BLE 服务中获取数据,并将各种变量打包到一个字节数组中。
解决方法
此处弃用的 withUnsafeBytes
版本是将底层指针绑定到已知类型 (Data.withUnsafeBytes<R,T>(_ body: (UnsafePointer<T>) throws -> R) rethrows -> R
) 的版本。
首选的替换是不以这种方式绑定的版本,并返回一个原始缓冲区指针(withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
);幸运的是,在这些之间转换只会改变你从指针中读取的方式:
extension Data {
func scanValueFromData<T>(start: Int = 0,invalid: T) -> (T,Int) {
let length = MemoryLayout<T>.size
guard self.count >= start + length else {
return (invalid,start + length)
}
return (self.subdata(in: start ..< start + length).withUnsafeBytes { $0.load(as: T.self) },start + length)
}
}
使用 UnsafeRawBufferPointer.load(as:)
,您可以安全地从缓冲区读取普通类型 T
。 (请注意,此方法对于调用非平凡类型不安全,但该方法的原始版本也是如此。)
如果您想进一步简化,可以避免重复start + length
:
func scanValueFromData<T>(start: Int = 0,Int) {
let length = MemoryLayout<T>.size
var value = invalid
if count >= start + length {
value = subdata(in: start ..< start + length).withUnsafeBytes { $0.load(as: T.self) }
}
return (value,start + length)
}
甚至更短,以可读性为代价:
func scanValueFromData<T>(start: Int = 0,Int) {
let length = MemoryLayout<T>.size
let value = count >= start + length ? subdata(in: start ..< start + length).withUnsafeBytes { $0.load(as: T.self) } : invalid
return (value,start + length)
}