Game Center - 使用 Swift 发送和接收数据
Game Center - sending and receiving data with Swift
我正在尝试将以下结构从一个播放器发送到另一个播放器:
struct GamePacket {
var action: String
var pointArray: [CGPoint]
}
我很难找出将 GamePacket
转换为 Data
并再次转换回来的正确方法。
这是我目前用于发送数据包的代码:
func send(packet: GamePacket) {
//convert GamePacket to Data here
let data = Data.init()
var remotePlayerArray = [GKPlayer]()
if let currentPlayer = self.currentPlayer, let match = self.match, let playerArray = self.match?.players {
for player in playerArray {
if player != currentPlayer {
remotePlayerArray.append(player)
}
}
do {
try match.send(data, to: remotePlayerArray, dataMode: GKMatchSendDataMode.reliable)
}
catch {
print("connectionError")
}
}
}
以及接收的代码:
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
//convert Data to GamePacket here
}
从一些用 ObjectiveC
编写的示例中,我设法使用类似于以下内容的方法将 GamePacket
转换为 Data
:
let data = NSData(bytes: &packet, length: MemoryLayout<GamePacket>.size) as Data
但是,我不知道如何在接收端将 Data
转换回 GamePacket
,我也不确定这是正确的方法。
非常感谢任何帮助。谢谢。
一个快速而肮脏的解决方案是这样的:
func encodeGamePacket(packet: GamePacket) -> NSData {
return NSData(bytes: &gamePacket, length: MemoryLayout<GamePacket>.size)
}
func decodeGamePacket(data: NSData) -> GamePacket? {
var tempBuffer:GamePacket? = nil
data.getBytes(&tempBuffer, length: MemoryLayout<GamePacket>.size)
return tempBuffer
}
我自己还没有在 swift 下弄乱直接地址,所以我不完全确定这是否是最好的方法。请注意,我使用了可选的 return 类型,您可以在代码中进行不同的设计(可能添加一些检查,打开变量并 return 它,或者在检查失败时抛出异常)。
或者,您可以设计一种方法,将 GamePacket
写入 String
(例如,为了提高可读性),然后您可以将其转换为 NSData
(字符串具有data
方法),或者您将 GamePacket
变成符合 NSCoding
的 class,它提供了将自身转换为 NSData
的方法。
使用Codable
struct GamePacket: Codable {
var action: String
var pointArray: [CGPoint]
}
然后您可以轻松转换为Data
:
func save<T: Encodable>(_ item: T, to url: URL) throws -> Data {
let encoder = JSONEncoder()
return try encoder.encode(item)
}
func load<T: Decodable>(from data:Data) throws -> T {
let decoder = JSONDecoder()
let item = try decoder.decode(T.self, from: data)
return item
}
我正在尝试将以下结构从一个播放器发送到另一个播放器:
struct GamePacket {
var action: String
var pointArray: [CGPoint]
}
我很难找出将 GamePacket
转换为 Data
并再次转换回来的正确方法。
这是我目前用于发送数据包的代码:
func send(packet: GamePacket) {
//convert GamePacket to Data here
let data = Data.init()
var remotePlayerArray = [GKPlayer]()
if let currentPlayer = self.currentPlayer, let match = self.match, let playerArray = self.match?.players {
for player in playerArray {
if player != currentPlayer {
remotePlayerArray.append(player)
}
}
do {
try match.send(data, to: remotePlayerArray, dataMode: GKMatchSendDataMode.reliable)
}
catch {
print("connectionError")
}
}
}
以及接收的代码:
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
//convert Data to GamePacket here
}
从一些用 ObjectiveC
编写的示例中,我设法使用类似于以下内容的方法将 GamePacket
转换为 Data
:
let data = NSData(bytes: &packet, length: MemoryLayout<GamePacket>.size) as Data
但是,我不知道如何在接收端将 Data
转换回 GamePacket
,我也不确定这是正确的方法。
非常感谢任何帮助。谢谢。
一个快速而肮脏的解决方案是这样的:
func encodeGamePacket(packet: GamePacket) -> NSData {
return NSData(bytes: &gamePacket, length: MemoryLayout<GamePacket>.size)
}
func decodeGamePacket(data: NSData) -> GamePacket? {
var tempBuffer:GamePacket? = nil
data.getBytes(&tempBuffer, length: MemoryLayout<GamePacket>.size)
return tempBuffer
}
我自己还没有在 swift 下弄乱直接地址,所以我不完全确定这是否是最好的方法。请注意,我使用了可选的 return 类型,您可以在代码中进行不同的设计(可能添加一些检查,打开变量并 return 它,或者在检查失败时抛出异常)。
或者,您可以设计一种方法,将 GamePacket
写入 String
(例如,为了提高可读性),然后您可以将其转换为 NSData
(字符串具有data
方法),或者您将 GamePacket
变成符合 NSCoding
的 class,它提供了将自身转换为 NSData
的方法。
使用Codable
struct GamePacket: Codable {
var action: String
var pointArray: [CGPoint]
}
然后您可以轻松转换为Data
:
func save<T: Encodable>(_ item: T, to url: URL) throws -> Data {
let encoder = JSONEncoder()
return try encoder.encode(item)
}
func load<T: Decodable>(from data:Data) throws -> T {
let decoder = JSONDecoder()
let item = try decoder.decode(T.self, from: data)
return item
}