I'm trying to receive messages in GameKit. The part of receiving the messages works well, but I can not figure out how to decode the data properly.
enum MessageType: Int, Codable {
case BestHost, GameBegin, YourTurn, PlayCard, GameOver
}
struct Message: Codable {
let messageType: MessageType
}
struct MessageBestHost: Codable {
let message: Message
let bestHostId: String
let bestHostName: String
}
I use the above infrastructure for sending and receiving my messages. For sending I encode the message as follows and then send it to all players:
func encode<T: Encodable>(_ item: T) throws -> Data {
let encoder = JSONEncoder()
return try encoder.encode(item)
}
func sendBestHost(player: GKPlayer) {
let message = MessageBestHost(message: Message(messageType: MessageType.BestHost), bestHostId: player.gamePlayerID, bestHostName: player.alias)
do {
try sendDataToAllPlayers(data: encode(message))
}
catch {
print("Error: \(error.localizedDescription)")
}
}
When receiving I use this method to decode the data:
func decode<T: Decodable>(from data:Data) throws -> T {
let decoder = JSONDecoder()
let item = try decoder.decode(T.self, from: data)
return item
}
let message: Message
do {
message = try decode (from: data)
print(message)
} catch {
print (error)
}
if message.messageType == MessageType.BestHost {
do {
let messageBestHost: MessageBestHost = try decode(from: data)
print("\(messageBestHost.bestHostName) hosts the game")
} catch {
print(error)
}
The problem now is. I first need to decode the message as type: Message in order to filter for the correct Subtype and do the magic for the referencing messageType. When trying to cast the data into a variable of type message, the decoding (obviously) fails because the sent data does not contain a messageType in the top hierarchical level.
Error: No value associated with key CodingKeys(stringValue: \"messageType\", intValue: nil)
Without being able to filter for the messageType first I won't be able to distinguish between different messages and execute different methods.
I guess the solution might lay within my data infrastructure but I cant think of any way to make this work. Does anybody have a clue how to solve this problem?
I might try something like this:
import Foundation
enum MessageType: Int, Codable {
case BestHost, GameBegin, YourTurn, PlayCard, GameOver
}
struct Message: Codable {
let messageType: MessageType
let data: Data
}
struct MessageBestHost: Codable {
let bestHostId: String
let bestHostName: String
}
do {
// Serialize:
let messageBestHost = MessageBestHost(bestHostId: "id", bestHostName: "name")
let messageBestHostData = try JSONEncoder().encode(messageBestHost)
let message = Message(messageType: .BestHost, data: messageBestHostData)
let messageData = try JSONEncoder().encode(message)
try sendDataToAllPlayers(data: encode(message))
// Deserialize:
let messageReceived = try JSONDecoder().decode(Message.self, from: messageData)
if messageReceived.messageType == .BestHost {
let messageBestHostReceived = try JSONDecoder().decode(MessageBestHost.self, from: messageReceived.data)
print(messageBestHostReceived.bestHostId)
print(messageBestHostReceived.bestHostName)
}
} catch {
print("Error: \(error.localizedDescription)")
}
Also swift enum cases should start with lowercase letter
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.