On Cocoa Touch, if we update UI elements from a background thread, bad stuff happens.
Problem is, it doesn't happen all the time, so some mild background UI meddling might go unnoticed for a while until it kicks your right in the teeth.
Is there a way to make UIKit run in a pedantic mode so that as soon as someone updates an element from a background thread it crashes or logs something to the console?
You can check yourself if you are doing stuff on the main thread or not before doing your UI updates. I've written myself the following macros:
/// Stick this in code you want to assert if run on the main UI thread.
#define DONT_BLOCK_UI() \
NSAssert(![NSThread isMainThread], @"Don't block the UI thread please!")
/// Stick this in code you want to assert if run on a background thread.
#define BLOCK_UI() \
NSAssert([NSThread isMainThread], @"You aren't running in the UI thread!")
I tend to group my code in methods where method A does some processing and then calls method B, which does the UI updates. At the beginning of method B I stick the BLOCK_UI() macro, which will assert if it is not being run on the UI. Also, for the long running tasks I use the other macro. I've put these macros and more random stuff at https://github.com/gradha/ELHASO-iOS-snippets which you may find useful.
These macros require discipline in using them, unfortunately. A more intrusive way to deal with such situations could be to wrap all the SDK interface objects through a proxy (maybe swizzling at launch?) which asserted if they were used not in the main thread. These proxying/swizzling would happen only in debug builds or simulator environment, to avoid bogging down real releases. I've considered doing this... but looks like a pain to do properly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With