Data withUnsafeBytes 已弃用

Data withUnsafeBytes is deprecated

我从我正在开发的应用程序中获得了这段代码。当 BLE 人离开团队时,我继承了这段代码。我不擅长低层次的东西和数据的东西。我是 UI/UX 前端人员,现在我确实需要亲自动手。这段代码现在有点旧并且使用了不推荐使用的代码。我一直试图让警告静音,但没有成功,但我总是以相同的代码或错误结束。

这是生成警告的代码。使用 withUnsafeBytes

时在 return 行
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{ [=10=].pointee }, start+length)
    }
}

此方法用于将字节数组解码为结构。我从 BLE 服务获取数据,各种变量被打包到一个字节数组中。

如果有任何解决此问题的方法或更好的方法来做 id。

此处弃用的 withUnsafeBytes 版本是将底层指针绑定到已知类型 (Data.withUnsafeBytes<R, T>(_ body: (UnsafePointer<T>) throws -> R) rethrows -> R) 的版本。

首选的替换版本是不以这种方式绑定的版本,returns 原始缓冲区指针 (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 { [=10=].load(as: T.self) }, start + length)
    }
}

使用 UnsafeRawBufferPointer.load(as:) 您可以安全地从缓冲区中读取一个普通类型 T。 (请注意,对于非平凡类型调用此方法安全,但该方法的原始版本也是如此。)

如果想进一步简化,可以避免重复start + length:

func scanValueFromData<T>(start: Int = 0, invalid: T) -> (T, Int) {
    let length = MemoryLayout<T>.size
    var value = invalid
    if count >= start + length {
        value = subdata(in: start ..< start + length).withUnsafeBytes { [=11=].load(as: T.self) }
    }

    return (value, start + length)
}

甚至更短,以可读性为代价:

func scanValueFromData<T>(start: Int = 0, invalid: T) -> (T, Int) {
    let length = MemoryLayout<T>.size
    let value = count >= start + length ? subdata(in: start ..< start + length).withUnsafeBytes { [=12=].load(as: T.self) } : invalid
    return (value, start + length)
}