1

我从我正在开发的应用程序中获得了此代码。当 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 服务获取数据,并将各种变量打包成一个字节数组。

如果有任何一个可以解决这个问题或更好的方法来做 id。

4

1 回答 1

0

这里不推荐使用的版本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, invalid: T) -> (T, 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, invalid: T) -> (T, 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)
}
于 2021-06-09T15:51:01.030 回答