Swift: расшифровка сообщения, отправленного из GameKit - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь получать сообщения в GameKit. Часть получения сообщений работает хорошо, но я не могу понять, как правильно декодировать данные.

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
}

Я использую вышеупомянутую инфраструктуру для отправки и получения моих сообщений. Для отправки я кодирую сообщение следующим образом, а затем отправляю его всем игрокам:

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)")
    }
}

При получении я использую этот метод для декодирования данных:

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)
}

Проблема сейчас в том. Сначала мне нужно декодировать сообщение как type: Message, чтобы отфильтровать правильный подтип и выполнить magi c для ссылочного messageType. При попытке преобразовать данные в переменную типа message декодирование (очевидно) завершается неудачно, поскольку отправленные данные не содержат messageType на верхнем иерархическом уровне.

Error: No value associated with key CodingKeys(stringValue: \"messageType\", intValue: nil)

Без возможности фильтрации по сначала messageType Я не смогу различить guish между разными сообщениями и выполнять разные методы.

Полагаю, что решение может лежать в моей инфраструктуре данных, но я не могу придумать, как это сделать Кто-нибудь знает, как решить эту проблему?

1 Ответ

1 голос
/ 31 марта 2020

Я мог бы попробовать что-то вроде этого:

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)")
}


Также быстрые перечисления должны начинаться со строчной буквы

...