Reputation: 525
I am trying to send the following structure from one player to another:
struct GamePacket {
var action: String
var pointArray: [CGPoint]
}
I'm having a hard time figuring out the correct way to convert the GamePacket
to Data
and back again.
Here is the code I have so far for sending packets:
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")
}
}
}
And the code for receiving:
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
//convert Data to GamePacket here
}
From some samples written in ObjectiveC
, I managed to convert the GamePacket
to Data
using something simmilar to the following:
let data = NSData(bytes: &packet, length: MemoryLayout<GamePacket>.size) as Data
However, I can't figure out how to convert the Data
back to a GamePacket
on the receiving end, nor am I sure this is the correct way to do it.
Any help is greatly apreciated. Thank you.
Upvotes: 4
Views: 955
Reputation: 3068
Codable
struct GamePacket: Codable {
var action: String
var pointArray: [CGPoint]
}
Then you can convert to Data
easily:
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
}
Upvotes: 4
Reputation: 4434
A quick and dirty solution would be something like this:
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
}
I have not messed with direct addresses myself under swift yet, so I am not entirely sure whether this is the best approach. Note that I used an optional return type, you can design this differently in your code (maybe add some checks, unwrap the variable and return it or throw an exception when the checks fail).
Alternatively you could design a method that writes your GamePacket
into a String
(for readability, for example), which you can in turn transform into NSData
(String has a data
method) or you turn GamePacket
into an NSCoding
compliant class that offers methods to convert itself into NSData
as well.
Upvotes: 2