Swift:解码从 GameKit 发送的消息
Posted
技术标签:
【中文标题】Swift:解码从 GameKit 发送的消息【英文标题】:Swift: Decode message sent from GameKit 【发布时间】:2020-03-31 17:09:23 【问题描述】:我正在尝试在 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)
现在的问题是。我首先需要将消息解码为类型:消息,以便过滤正确的子类型并为引用消息类型发挥作用。当尝试将数据转换为 message 类型的变量时,解码(显然)失败,因为发送的数据不包含顶层层级中的 messageType。
Error: No value associated with key CodingKeys(stringValue: \"messageType\", intValue: nil)
如果不能先过滤messageType,我将无法区分不同的消息并执行不同的方法。
我想解决方案可能位于我的数据基础架构中,但我想不出任何方法来完成这项工作。有人知道如何解决这个问题吗?
【问题讨论】:
会不会根据类型本身有不同类型的Message或MessageBestHost?如果是这样,那么也许这会有所帮助:***.com/questions/59270672/… 如果不是,那么我不明白为什么你不能先将其解码为 MessageBestHost,然后再对其进行过滤。mesasageType
提到的所有类型的消息。我只是以 MessageBestHost 为例。这就是为什么我不能一直将它解码为 MessageBestHost,因为 messageType 会改变并且不会总是包含相同的数据。我刚刚查看了提供的链接。在那里你使用协议。我无法将您的示例与我的示例联系起来,因为我不使用协议。您认为在这里使用协议是正确的方法吗?谢谢!
这取决于您需要如何使用 MessageBestHost。如果在数组中,那么它们应该符合相同的协议。
【参考方案1】:
我可能会尝试这样的事情:
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)")
Swift 枚举 case 也应该以小写字母开头
【讨论】:
以上是关于Swift:解码从 GameKit 发送的消息的主要内容,如果未能解决你的问题,请参考以下文章