Puede comprobar usted mismo si está haciendo cosas en el hilo principal o no antes de hacer sus actualizaciones de interfaz de usuario. Yo mismo he escrito las siguientes 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!")
tiendo a mi grupo de código en procedimientos en los que el método A hace algún procesamiento y luego llama al método B, que hace las actualizaciones de la interfaz de usuario. Al comienzo del método B, pego la macro BLOCK_UI(), que afirmará si no se está ejecutando en la UI. Además, para las tareas de larga ejecución utilizo la otra macro. He puesto estas macros y más cosas al azar en https://github.com/gradha/ELHASO-iOS-snippets, que pueden serle útiles.
Estas macros requieren disciplina al usarlas, desafortunadamente. Una forma más intrusiva de tratar con tales situaciones podría ser envolver todos los objetos de la interfaz SDK a través de un proxy (¿tal vez swizzling en el lanzamiento?) Que afirmaba que si no se usaban en el hilo principal. Estos proxying/swizzling ocurrirían solo en construcciones de depuración o en entornos de simulación, para evitar empantanar las versiones reales. He considerado hacer esto ... pero parece un dolor hacer bien.