Few days ago, I was reported a crash when BarcodeReader continuously scan barcodes and ClearAll button is tapped at the same time. At first glance, I can't imagine any possible causes because the entire work flow is pretty simple. I have four
PublishSubjectsending the notification when certain type of barcode is recognized or user taps the ClearAll button to remove all the history.
PublishSubject as a way to send notification or delegation callback. All the actions are handled on the main thread and they couldn't go wrong, right?
When I saw the stack as crash happens, it told me the
UIInternalInconsistency exception is thrown. This is a typical scenario where your data source and UI are out of sync, which is weird to me that all the changes to
BusinessModel are done on the main thread and there shouldn't be any race condition.
I tried to add more logs and I found something beyond my expectation. The order of the Rx callbacks are different from that of user's actions. And when I looked twice at the
PublishSubject, I realized that different
PublishSubjects actually work on different queue, which definitely results in race condition that could cause crashes.
From this point, I learn that
PublishSubject is not delegate. You need to notify changes of a certain data model in a single
PublishSubject(single queue). And more importantly you need to understand the design of Rx and not just apply your old workflow design to the usage of Rx.