将 Int64 转换为 UUID

Posted

技术标签:

【中文标题】将 Int64 转换为 UUID【英文标题】:Convert Int64 to UUID 【发布时间】:2022-01-05 07:20:13 【问题描述】:

如何将 swift 的 Int64 转换为 UUID 并返回?由于UUID 是128 位,我想用零填充前64 位。

我可以从uuid_t 构造UUID,它是UInt8 的元组,通过移位和转换Int64 八次。

有没有更好的方法?

【问题讨论】:

虽然您可以从 64 位值创建一个 128 位值,但您会拥有 UUID 吗?当然,这对你来说可能无关紧要。 @CRD 我正在使用 CXProvider,它使用 UUID 作为调用标识符,而我们在框架中使用 Int64。我需要将 CXProvider 的 id 映射到我们的 id。 【参考方案1】:

UUID 是 Foundation 类型 NSUUID 的 Swift 覆盖类型, 后者可以从字节缓冲区创建。用一点点 指针杂耍这也适用于 64 位整数:

let vals: [UInt64] = [0, 0x123456789abcdef]

let uuid = vals.withUnsafeBufferPointer 
    $0.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: 16) 
         NSUUID(uuidBytes: $0) as UUID
    


print(uuid) // 00000000-0000-0000-EFCD-AB8967452301

【讨论】:

【参考方案2】:

严格回答你的问题

“最简单”的做法(不依赖CollectionTypeTuple的内存布局,也不需要NSUUID)是:

extension UUID 
    init(number: Int64) 
        var number = number
        let numberData = Data(bytes: &number, count: MemoryLayout<Int64>.size)

        let bytes = [UInt8](numberData)

        let tuple: uuid_t = (0, 0, 0, 0, 0, 0, 0, 0,
                             bytes[0], bytes[1], bytes[2], bytes[3],
                             bytes[4], bytes[5], bytes[6], bytes[7])

        self.init(uuid: tuple)
    

    var intValue: Int64? 
        let tuple = self.uuid
        guard tuple.0 == 0 && tuple.1 == 0 && tuple.2 == 0 && tuple.3 == 0 &&
              tuple.4 == 0 && tuple.5 == 0 && tuple.6 == 0 && tuple.7 == 0 else 
                return nil
        

        let bytes: [UInt8] = [tuple.8, tuple.9, tuple.10, tuple.11,
                              tuple.12, tuple.13, tuple.14, tuple.15]

        let numberData = Data(bytes: bytes)

        let number = numberData.withUnsafeBytes  $0.pointee  as Int64

        return number
    

另外,您可能想要throw/fatalError 而不是返回nil

创建有效的UUIDs

为了完整起见(并使其实际上可以创建有效的 UUID),我添加了一种从 2 Int64 创建它的方法,并使用该方法重写了您的问题的答案:

UUID 创建自 (Int64, Int64)

extension UUID 
    init(numbers: (Int64, Int64)) 
        var firstNumber = numbers.0
        var secondNumber = numbers.1
        let firstData = Data(bytes: &firstNumber, count: MemoryLayout<Int64>.size)
        let secondData = Data(bytes: &secondNumber, count: MemoryLayout<Int64>.size)

        let bytes = [UInt8](firstData) + [UInt8](secondData)

        let tuple: uuid_t = (bytes[0], bytes[1], bytes[2], bytes[3],
                             bytes[4], bytes[5], bytes[6], bytes[7],
                             bytes[8], bytes[9], bytes[10], bytes[11],
                             bytes[12], bytes[13], bytes[14], bytes[15])

        self.init(uuid: tuple)
    

    var intTupleValue: (Int64, Int64) 
        let tuple = self.uuid

        let firstBytes: [UInt8] = [tuple.0, tuple.1, tuple.2, tuple.3,
                                   tuple.4, tuple.5, tuple.6, tuple.7]

        let secondBytes: [UInt8] = [tuple.8, tuple.9, tuple.10, tuple.11,
                                    tuple.12, tuple.13, tuple.14, tuple.15]

        let firstData = Data(bytes: firstBytes)
        let secondData = Data(bytes: secondBytes)

        let first = firstData.withUnsafeBytes  $0.pointee  as Int64
        let second = secondData.withUnsafeBytes  $0.pointee  as Int64

        return (first, second)
    

UUIDInt64 创建(用 0 填充 MSB)

extension UUID 
    init(number: Int64) 
        self.init(numbers: (0, number))
    

    var intValue: Int64? 
        let (first, second) = intTupleValue
        guard first == 0 else  return nil 

        return second
    

【讨论】:

这仍然可以稍微简化,例如第二种方法中的let number = numberData.withUnsafeBytes $0.pointee as Int64,比较round trip Swift number types to/from Data。【参考方案3】:

您也可以使用withUnsafeBytes 并将其加载为UUID

let vals: [UInt64] = [0, 0x123456789abcdef]
let uuid = vals.withUnsafeBytes  $0.load(as: UUID.self) 
print(uuid) //  00000000-0000-0000-EFCD-AB8967452301

【讨论】:

以上是关于将 Int64 转换为 UUID的主要内容,如果未能解决你的问题,请参考以下文章

怎么将UUID保存成int

快速将双精度转换为 Int64

如何将键值映射转换为 int 切片 [关闭]

将 int64_t 转换为 NSInteger

Tensorflow TypeError:无法将'numpy.int64'对象隐式转换为str

将 JSON 对象脱盐到数据表时将值“1D”转换为类型“System.Int64”时出错