提问者:小点点

Swift数据转换为UInt64


我阅读了一些Apple文档,但我不能在对象中做这件事。我通过蓝牙在Data类型的变量中接收一个unix时间戳值,我不想将其转换为UInt64 var来填充UIDatePicker,但我实现的函数给我带来了错误:“致命错误:Un安全RawBufferPoint. load出界”

你有什么建议吗?我正在使用Swift 5.1

这是我的代码:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var datePicker: UIDatePicker!

    private func setDate(value: Data) {
        let date = Date(timeIntervalSince1970: TimeInterval(value.uint64))
        datePicker.setDate(date, animated: true)
    }
}
extension Data {
    var uint64: UInt64 {
        withUnsafeBytes { $0.load(as: UInt64.self) }
    }
}

共2个答案

匿名用户

当数据中没有足够的字节来形成UInt64(少于8个)时,我会收到该错误。这里很可能就是这种情况。

解决这个问题的一种方法是更改uint64,以便它处理没有足够字节的情况。当字节不够时,它可以用0填充数据,直到有足够的字节:

extension Data {
  var uint64: UInt64 {
        get {
            if count >= 8 {
                return self.withUnsafeBytes { $0.load(as: UInt64.self) }
            } else {
                return (self + Data(repeating: 0, count: 8 - count)).uint64
            }
        }
    }
}

这是假设一个little-endian设备和little-endian数据。如果数据是大端:

extension Data {
  var uint64: UInt64 {
        get {
            if count >= 8 {
                return self.withUnsafeBytes { $0.load(as: UInt64.self).bigEndian }
            } else {
                return (Data(repeating: 0, count: 8 - count) + self).uint64
            }
        }
    }
}

或者,如果可以,请在您的蓝牙设备上解决此问题,使其始终发送8个字节。

匿名用户

如果您知道您的蓝牙设备只会发送小端四字节值,那显然只有32位。我不知道您为什么要尝试从您知道只是UInt32(或其他32位类型)的东西中提取UInt64。所以我建议:

extension Data {
    var uint32: UInt32 { 
        withUnsafeBytes { $0.load(as: UInt32.self) }
    }
}

或者你可以使endianness明确:

extension Data {
    var uint32: UInt32 { 
        withUnsafeBytes { $0.load(as: UInt32.self).littleEndian }
    }
}