My question is, why, specifically?
Because Apple specifically tells us, on the UIView reference page, that:
Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application.
There's a similar warning in the Core Image Programming Guide:
CIContext
and CIImage
objects are immutable, which means each can be shared safely among threads. Multiple threads can use the same GPU or CPU CIContext
object to render CIImage
objects. However, this is not the case for CIFilter
objects, which are mutable. A CIFilter
object cannot be shared safely among threads. If your app is multithreaded, each thread must create its own CIFilter
objects. Otherwise, your app could behave unexpectedly.
And there's a further clue in Technical Q&A QA1238, which relates to MacOS X but probably applies to iOS as well:
Quartz is thread safe on the whole, but individual Quartz objects are not. In general, you can operate on any object on any thread as long as you guarantee that no two threads are operating on the same object simultaneously. The easiest way to achieve this is to not share your objects between threads.
So it certainly seems that UIView
is not thread safe. A view is a mutable object that the main thread needs access to, so trying to modify a view from a different thread is bound to cause problems.
What types of issues could one expect when updating UI away from the main thread?
Imagine that you're working with some object and the data stored in the object changed at random times, all by itself and with no warning. That's what happens when multiple threads all use a mutable object without taking steps to synchronize their access to the object. That can lead to all kinds of problems, from outright crashes to intermittent and hard to find bugs.
Setting the text of a label seems pretty innocuous, right? It's just data: it's pretty unlikely that two threads are going to try to set the label's text at exactly the same time, and even if they do it seems like the worst that might happen is that the label could contain some garbled string. But it's worse than that -- first, the text
property takes a NSString*
, i.e. a pointer, and if the pointer gets garbled it could easily lead to a memory exception, crashing the app. Also, whenever you set a label's text, the label schedules itself for redrawing. That could put the run loop or the drawing system into an inconsistent state.
The list of bad things that could happen if you ignore the advice about limiting updates to the main thread is impossible to enumerate completely, and probably changes from one iOS release to the next. But ultimately, we really don't need the list -- we just need to know how to avoid the problem.
Limit UI updates to the main thread.