Swift 在设备之间传输CGPoint的最佳方式是什么?
我正在用swift开发一个基于回合的游戏,其中所有内容都必须转换为NSData。现在我已经被“NS的东西”困扰了很多天了。因为CGPoint不是一个对象而是一个结构,所以它不能直接转换为NSData,CGPoint内部的CGFloat也是如此。我想做的是:(只是一个想法,不确定它是否有效。)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 将它们合
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