This is where I try to fetch and decode data inside ChatReceivedMessageModel. I do get data but while decoding I am getting codingkeys error.
func listenDeleted() {
socket?.off("deletedmessage")
socket?.on("deletedmessage") { data, ack in
let messageDict = data.last as! NSDictionary
let messageDataObject = try? JSONSerialization.data(withJSONObject: messageDict, options: [])
guard let messageData = messageDataObject else { return }
do {
let jsonDecoder = JSONDecoder()
let message = try jsonDecoder.decode(ChatReceivedMessageModel.self, from: messageData)
print("success")
let messageID = message.messageId ?? ""
let usertoConnect = message.userToConnect ?? ""
let room = message.room ?? ""
let userInfo = ["messageId": messageID]
NotificationCenter.default.post(name: Notification.Name("messageDeleted"), object: nil, userInfo: userInfo)
} catch {
print("Unexpected error: \(error).")
}
}
That is the related model
class ChatReceivedMessageModel: Serializable {
var room: String?
var message: String?
var userToConnect: String?
var userFullName: String?
var senderId: String?
var senderPhotoUrl: String?
var creationTimestamp: Int64?
var messageId: String?
init(room: String, message: String, userToConnect: String, userFullName: String, senderId: String, senderPhotoUrl: String, creationTimestamp: Int64, messageId: String) {
self.room = room
self.message = message
self.userToConnect = userToConnect
self.userFullName = userFullName
self.senderId = senderId
self.senderPhotoUrl = senderPhotoUrl
self.creationTimestamp = creationTimestamp
self.messageId = messageId
}
enum CodingKeys: String, CodingKey {
case room
case message
case userToConnect
case userFullName
case senderId
case senderPhotoUrl
case creationTimestamp
case messageId
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
room = try values.decode(String.self, forKey: .room)
message = try values.decodeIfPresent(String.self, forKey: .message)
userToConnect = try values.decode(String.self, forKey: .userToConnect)
userFullName = try values.decode(String.self, forKey: .userFullName)
senderId = try values.decode(String.self, forKey: .senderId)
senderPhotoUrl = try values.decode(String.self, forKey: .senderPhotoUrl)
creationTimestamp = try values.decode(Int64.self, forKey: .creationTimestamp)
messageId = try values.decode(String.self, forKey: .messageId)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(room, forKey: .room)
try container.encode(message, forKey: .message)
try container.encode(userToConnect, forKey: .userToConnect)
try container.encode(userFullName, forKey: .userFullName)
try container.encode(senderId, forKey: .senderId)
try container.encode(senderPhotoUrl, forKey: .senderPhotoUrl)
try container.encode(creationTimestamp, forKey: .creationTimestamp)
try container.encode(messageId, forKey: .messageId)
}
func getChatUserModelType() -> ChatUserModel {
var model = ChatUserModel()
model.communityUserId = self.senderId
model.name = self.userFullName
model.photoUrl = self.senderPhotoUrl
return model
}
}
And the error is;
Unexpected error: keyNotFound(CodingKeys(stringValue: "userFullName", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "userFullName", intValue: nil) ("userFullName").", underlyingError: nil)).
I also added breakpoints outcome as in the image
CodePudding user response:
The problem is here
userFullName = try values.decode(String.self, forKey: .userFullName)
In the mentioned line you tell decoder to decode key named userFullName
and throw an error if it doesn't exist and this happens when the key is not here like in your error and same also for any property that you define as optional but decode like a non-optional
You need to decode optionally with try?
inside required init(from decoder: Decoder) throws {
userFullName = try? values.decode(String.self, forKey: .userFullName)
OR use decodeIfPresent
userFullName = try values.decodeIfPresent(String.self, forKey: .userFullName)
BTW in your current code you don't need implementation of any of these ones
1- enum CodingKeys: String, CodingKey { // You don't change any property name
2- required init(from decoder: Decoder) throws { // this occurs automatically when conform to Decodable/Codable
3- func encode(to encoder: Encoder) throws { // this occurs automatically when conform to Encodable/Codable
So you can remove them completely from your current code