Swift 在设备之间传输CGPoint的最佳方式是什么?

Swift 在设备之间传输CGPoint的最佳方式是什么?,swift,nsdata,nsnumber,nskeyedarchiver,cgpoint,Swift,Nsdata,Nsnumber,Nskeyedarchiver,Cgpoint,我正在用swift开发一个基于回合的游戏,其中所有内容都必须转换为NSData。现在我已经被“NS的东西”困扰了很多天了。因为CGPoint不是一个对象而是一个结构,所以它不能直接转换为NSData,CGPoint内部的CGFloat也是如此。我想做的是:(只是一个想法,不确定它是否有效。) 将CGPoint转换为2个不同的浮点 使用Float创建nsnumer 使用NSNumber创建NSData 在另一个设备中将NSData转换回NSNumber 将NSNumber转换为Float 将它们合

我正在用swift开发一个基于回合的游戏,其中所有内容都必须转换为NSData。现在我已经被“NS的东西”困扰了很多天了。因为CGPoint不是一个对象而是一个结构,所以它不能直接转换为NSData,CGPoint内部的CGFloat也是如此。我想做的是:(只是一个想法,不确定它是否有效。)

  • 将CGPoint转换为2个不同的浮点
  • 使用Float创建nsnumer
  • 使用NSNumber创建NSData
  • 在另一个设备中将NSData转换回NSNumber
  • 将NSNumber转换为Float
  • 将它们合并回CGPoint
  • 这条路太复杂了。 是否有更好的实施方法或最佳实践?提前感谢


    PS:NSKeyedArchiver由于其性能而不应被考虑。(不确定!)

    注意:如果您不需要高性能,您最好接受Rob Napier的建议(
    NSStringFromCGPoint
    /
    CGPointFromString
    ),因为它更简单、更容易调试。然而,许多游戏都有很高的性能要求,并且每个游戏循环需要不止一个
    CGPoint
    。这是我的假设

    假设发送方和接收方的
    CGFloat
    类型相同(32位或64位):

    var pointToSend = CGPointMake(100, 200)
    let data = NSData(bytes: &pointToSend, length: MemoryLayout<CGPoint>.size)
    // send data to other device
    
    // receive data on other device
    if (data.length == MemoryLayout<CGPoint>.size) {
        var receivedPoint = UnsafePointer<CGPoint>(data.bytes).memory
    } else {
        // error
    }
    

    注意:如果您不需要高性能,您最好接受Rob Napier的建议(
    NSStringFromCGPoint
    /
    CGPointFromString
    ),因为它更简单、更容易调试。然而,许多游戏都有很高的性能要求,并且每个游戏循环需要不止一个
    CGPoint
    。这是我的假设

    假设发送方和接收方的
    CGFloat
    类型相同(32位或64位):

    var pointToSend = CGPointMake(100, 200)
    let data = NSData(bytes: &pointToSend, length: MemoryLayout<CGPoint>.size)
    // send data to other device
    
    // receive data on other device
    if (data.length == MemoryLayout<CGPoint>.size) {
        var receivedPoint = UnsafePointer<CGPoint>(data.bytes).memory
    } else {
        // error
    }
    

    编码
    CGPoint
    的最简单方法是使用
    NSStringFromCGPoint
    CGPointFromString
    。这将消除所有32/64位的问题,否则您将面临这些问题

    这种运输非常便宜(不到一个MTU,所以这并不重要)。唯一可能昂贵的事情是字符串解析,几乎可以肯定的是,将其连接到网络上的成本已经超过了它


    但是,如果您有一个非常紧密的网络协议并且需要最佳性能,我会将
    CGPoint
    转换为
    (Float32,Float32)
    ,或者更好的是,如果您实际上不需要非整数值,则转换为
    (Int32,Int32)
    。正如@robmayoff所建议的,这很容易编码,前提是你不在乎endianness。有了Int,您可以很容易地使用
    Int.bigEndian
    Int(bigEndian:)
    来处理这个问题。

    编码
    CGPoint
    最简单的方法是使用
    NSStringFromCGPoint
    CGPointFromString
    。这将消除所有32/64位的问题,否则您将面临这些问题

    这种运输非常便宜(不到一个MTU,所以这并不重要)。唯一可能昂贵的事情是字符串解析,几乎可以肯定的是,将其连接到网络上的成本已经超过了它


    但是,如果您有一个非常紧密的网络协议并且需要最佳性能,我会将
    CGPoint
    转换为
    (Float32,Float32)
    ,或者更好的是,如果您实际上不需要非整数值,则转换为
    (Int32,Int32)
    。正如@robmayoff所建议的,这很容易编码,前提是你不在乎endianness。使用Int,您可以轻松地使用
    Int.bigEndian
    Int(bigEndian:)
    来处理此问题。

    谢谢。它工作得很好。现在我正在研究“UnsafePointer”,以了解为什么它被称为“不安全的”。)它不安全有几个原因。它不提供内存管理,因此如果底层对象消失,它可能会成为一个悬空的指针(这在这里不可能发生,因为指针会立即被销毁)。它也不安全,因为它规避了类型安全。例如,如果
    data.bytes
    太短,您在这里读取的内存无效,可能会崩溃。如果
    data
    实际上没有指向
    CGPoint
    ,您可能会读取垃圾(这对
    CGPoint
    来说并不重要,但可能会损坏其他类型的对象)。不说这个答案是没有用的;它就是不安全。
    UnsafePointer
    允许您执行不安全的操作(如使程序崩溃或损坏堆),因为它绕过了类型系统和引用计数系统。与任何强大的工具一样,安全使用取决于您。我已经更新了我的答案,让它更安全。嘿,
    sizeofValue
    sizeof
    的功能是什么?您如何同时转换多个值,例如一个点和一个角度?我已经更新了我的答案,使用
    MemoryLayout
    (在我发布此答案两年后在Swift 3.0中引入)。谢谢。它工作得很好。现在我正在研究“UnsafePointer”,以了解为什么它被称为“不安全的”。)它不安全有几个原因。它不提供内存管理,因此如果底层对象消失,它可能会成为一个悬空的指针(这在这里不可能发生,因为指针会立即被销毁)。它也不安全,因为它规避了类型安全。例如,如果
    data.bytes
    太短,您在这里读取的内存无效,可能会崩溃。如果
    data
    实际上没有指向
    CGPoint
    ,您可能会读取垃圾(这对
    CGPoint
    来说并不重要,但可能会损坏其他类型的对象)。不说这个答案是没有用的;它就是不安全。
    UnsafePointer
    允许您执行不安全的操作(如使程序崩溃或损坏堆),因为它绕过了类型系统和引用计数系统。与任何强大的工具一样,安全使用取决于您。我已经更新了我的答案,让它更安全。嘿,这里有什么函数
    sizeo