Я разрабатываю приложение для чата, где я мог бы получать несколько сообщений одновременно, что приводит к зависанию приложения. Ниже приведен мой сокет приемник:
func receiveNewDirectMessages() {
self.socket?.on(EventListnerKeys.message.rawValue, callback: { (arrAckData, ack) in
print_debug(arrAckData)
guard let dictMsg = arrAckData.first as? JSONDictionary else { return }
guard let data = dictMsg[ApiKey.data] as? JSONDictionary else { return }
guard let chatData = data[ApiKey.data] as? JSONDictionary else { return }
guard let messageId = chatData[ApiKey._id] as? String , let chatId = chatData[ApiKey.chatId] as? String else { return }
if MessageModel.getMessageModel(msgId: messageId) != nil { return }
let isChatScreen = self.isChatScreen
let localMsgId = "\(arc4random())\(Date().timeIntervalSince1970)"
if let senderInfo = data[ApiKey.senderInfo] as? JSONDictionary, let userId = senderInfo[ApiKey.userId] as? String, userId != User.getUserId() {
_ = AppUser.writeAppUserModelWith(userData: senderInfo)
}
let msgModel = MessageModel.saveMessageData(msgData: chatData, localMsgId: localMsgId, msgStatus: 2, seenByMe: false)
let chatModel = ChatModel.saveInboxData(localChatId: msgModel.localChatId, inboxData: chatData)
if isChatScreen {
self.emitMessageStatus(msgId: messageId, chatId: chatId, socketService: .messageStatus, status: .delivered)
self.emitMessageStatus(msgId: messageId, chatId: chatId, socketService: .messageStatus, status: .seen)
} else {
ChatModel.updateUnreadCount(localChatId: chatModel.localChatId, incrementBy: 1)
self.emitMessageStatus(msgId: messageId, chatId: chatId, socketService: .messageStatus, status: .delivered)
}
TabController.shared.updateChatBadgeCount()
})
}
Что происходит выше:
1. Я получаю все недоставленные сообщения ОДИН-О-ОДИН в этом слушателе сокета.
2. Извлечение данных сообщения
3. Сохранение полученной информации об отправителе в Realm DB
4. Сохранение модели сообщения в БД области
5. СОХРАНЕНИЕ / ОБНОВЛЕНИЕ Тема чата в БД областей
6. Передача подтверждения для полученного сообщения
7. Обновить счетчик чата на панели вкладок
Ниже мой отправитель для подтверждения доставки сообщения.
func emitMessageStatus(msgId: String, chatId: String, socketService: SocketService, status: MessageStatusAction) {
// Create Message data packet to be sent to socket server
var msgDataPacket = [String: Any]()
msgDataPacket[ApiKey.type] = socketService.type
msgDataPacket[ApiKey.actionType] = socketService.listenerType
msgDataPacket[ApiKey.data] = [
ApiKey.messageId: msgId,
ApiKey.chatId: chatId,
ApiKey.userId: User.getUserId(),
ApiKey.statusAction: status.rawValue
]
// send the messsage data packet to socket server & wait for the acknowledgement
self.emit(with: EventListnerKeys.socketService.rawValue, msgDataPacket) { (arrAckData) in
print_debug(arrAckData)
guard let dictMsg = arrAckData.first as? JSONDictionary else { return }
if let msgData = dictMsg[ApiKey.data] as? [String: Any] {
// Update delivered Seen Status here
if let msgId = msgData[ApiKey.messageId] as? String, let actionType = msgData[ApiKey.statusAction] as? String, let msgStatusAction = MessageStatusAction(rawValue: actionType) {
switch msgStatusAction {
case .delivered:
if let deliveredTo = msgData[ApiKey.deliveredTo] as? [[String: Any]] {
_ = MessageModel.updateMsgDelivery(msgId: msgId, deliveredTo: deliveredTo)
}
case .seen:
if let seenBy = msgData[ApiKey.seenBy] as? [[String: Any]] {
_ = MessageModel.updateMsgSeen(msgId: msgId, seenBy: seenBy)
}
case .pin:
MessageModel.clearPinnedMessages(chatId: chatId)
if let pinTime = msgData[ApiKey.pinTime] as? Double {
MessageModel.updatePinnedStatus(msgId: msgId, isPinned: true, pinTime: pinTime)
}
case .unPin:
if let pinTime = msgData[ApiKey.pinTime] as? Double {
MessageModel.updatePinnedStatus(msgId: msgId, isPinned: false, pinTime: pinTime)
}
case .delete:
MessageModel.deleteMessage(msgId: msgId)
case .ackMsgStatus, .like, .unlike:
break
}
}
}
}
}
Что происходит выше:
- Инкапсуляция всей связанной информации для подтверждения события
- Обновление базы данных области после доставки подтверждения
Теперь я не могу игнорировать идеальную политику потоков. Что писать в фоновом потоке, а что писать в главном потоке. Однако я попытался сделать это, но это приводит к случайным сбоям или потерям пакетов.
Может кто-нибудь, пожалуйста, ведите меня вперед по этой теме. Буду очень признателен.