Today I experienced that notifications are delayed.
If I add a new item to a tableView's dataSource array, and I use notifications to update that tableView (insert row) (because it's in another ViewController),
then if I do it 2 times at the same time, my app crashes: because notifications are arriving late.
More details:
I have a TabController
:
Chat.shared.receiveMessage { message in
print("1: received msg, added to array")
ChatStore.shared.messages.append(message)
print("2: sending noti")
NotificationCenter.default.post(name: .updateChatMessages, object: nil)
}
And a ChatMessageViewController
that recieves the .updateChatMessages
notification
@objc func notification_updateChatMessages(){
DispatchQueue.main.async {
print("3: noti arrived")
self.tableView.beginUpdates()
self.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
self.tableView.endUpdates()
}
}
The problem is, that Notifications are delayed somehow.
If 2 messages are received at the same thime, then the following happens (output):
1: received msg, added to array
2: sending noti
-
1: received msg, added to array
2: sending noti
-
3: noti arrived
3: noti arrived
The app crashes, because when the first notification arrives, then already both 2 messages were added to the dataSource..
Instead the output should look something like this:
1: received msg, added to array
2: sending noti
3: noti arrived
-
1: received msg, added to array
2: sending noti
3: noti arrived
Are the notifications delayed? How could I fix that?
UPDATE 1: added receiveMessage() to thread as requested
Chat.swift (part where it receives messages)
func receiveMessage(completion: @escaping (String?)->()){
socket.on("message") {
(data, socketAck) -> Void in
guard let dataArray = data[0] as? [String: Any] else {
return
}
guard let message = dataArray["message"] as? String else {
return
}
return completion(message)
}
}
The issue is most likely with using DispatchQueue.main.async
. That will add a closure to be run in the next iteration of the main run loop. If two notifications are fired between runloop iterations then multiple blocks will be queued up and run causing the issue your seeing.
Theres a couple options that could work
3: noti arrived
look at the datastore a
calculate how many rows it should insert.DispatchQueue.main.sync
instead. This is highly dependant on queue you're receiving socket messages on and could lead to worse issues.