我正在使用swift开发一个回合制游戏,其中所有内容都必须转换为NSData。现在我一直被困在" NS-stuff"很多天因为CGPoint不是对象而是结构,所以它不能直接转换为NSData,CGPoint中的CGFloat也是如此。我想做的是:(只是一个想法,不确定它是否有效。)
这种方式太复杂了。 有没有更好的方法来实现它或任何最佳实践?在此先感谢!!!
PS:NSKeyedArchiver不应该因为它的性能而被考虑。 (不确定!)
答案 0 :(得分:3)
编码CGPoint
的最简单方法是使用NSStringFromCGPoint
和CGPointFromString
。这消除了您可能面临的所有32/64位问题。
这种运输非常便宜(少于一个MTU,因此它并不重要)。唯一可能是昂贵的是字符串解析,这几乎肯定会被放在线上的成本所淹没。
但是,如果您的网络协议非常紧凑并且需要最佳性能,我会将CGPoint
转换为(Float32, Float32)
,或者更好的是(Int32, Int32)
,如果您没有&#39} ; t实际上需要非整数值。 @robmayoff很容易编码,假设您不关心字节序。使用Int,您可以轻松地使用Int.bigEndian
和Int(bigEndian:)
来处理此问题。
答案 1 :(得分:1)
注意:如果你不需要高性能,你可能会更好地使用Rob Napier的建议(NSStringFromCGPoint
/ CGPointFromString
),因为它更简单,更容易调试。但是,许多游戏都有很高的性能要求,每个游戏循环需要不止一个CGPoint
。这些是我的假设。
假设CGFloat
在发送方和接收方上都是相同的类型(32位或64位):
var pointToSend = CGPointMake(100, 200)
let data = NSData(bytes: &pointToSend, length: sizeof(CGPoint))
// send data to other device
// receive data on other device
if (data.length == sizeof(CGPoint)) {
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: sizeofValue(pairToSend))
// receiver
if (data.length == sizeof(DoublePoint)) {
var receivedPair = UnsafePointer<DoublePoint>(data.bytes).memory
var receivedPoint = CGPointMake(CGFloat(receivedPair.x), CGFloat(receivedPair.y))
} else {
// error
}