我正在快速开发基于回合的游戏,其中所有内容都必须转换为NSData。现在,我已经被困在“ NS-stuff”上很多天了。由于CGPoint不是对象而是结构,因此无法直接将其转换为NSData,因此CGPoint中的CGFloat也是如此。我正在尝试做的是:(只是一个主意,不确定是否可行。)
这种方式太复杂了。有没有更好的方法来实施它或任何最佳做法?提前谢谢!!
PS:由于其性能,不应该考虑NSKeyedArchiver。 (不确定!)
最简单的编码CGPoint
的方法是使用NSStringFromCGPoint
和CGPointFromString
。这消除了您否则将面临的所有32/64位问题。
此传输非常便宜(少于一个MTU,因此并不重要)。唯一可能会很昂贵的是字符串解析,几乎可以肯定,将其放在电线上的开销不堪重负。
但是,如果您的网络协议非常严格并且需要最佳性能,那么如果您实际上不需要非整数值,则可以将CGPoint
转换为(Float32, Float32)
,或者更好的是将其转换为(Int32, Int32)
。假设您不关心字节序,这很容易按照@robmayoff的建议进行编码。使用Int,您可以轻松地使用Int.bigEndian
和Int(bigEndian:)
处理此问题。
注意:如果您不需要高性能,那么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
}
如果接收者的CGFloat
可能不同于发送者的:
typealias DoublePoint = (x: Double, y: Double)
// sender
var pointToSend = CGPointMake(100, 200)
var pairToSend = (Double(pointToSend.x), Double(pointToSend.y))
let data = NSData(bytes: &pointToSend, length: MemoryLayout.size(ofValue: pairToSend))
// receiver
if (data.length == MemoryLayout<DoublePoint>.size) {
var receivedPair = UnsafePointer<DoublePoint>(data.bytes).memory
var receivedPoint = CGPointMake(CGFloat(receivedPair.x), CGFloat(receivedPair.y))
} else {
// error
}