All updates should be done from the main thread. This has always
been the general recommendation for UIKit and that recommendation
extends to watchOS.
It might be helpful to understand the underlying reason for this
requirement. Keep in mind that, even with a centralized communication
channel to serialize changes, many problems arise when you attempt to
manipulate UI state from background threads. For example, while the
serialization channel can prevent multiple UI commands from attempting
to simultaneously execute, it can’t control the order in which
unrelated commands will execute. Consider the following 2 blocks:
block 1 {
DoUIChange1
DoUIChange2
}
block 2 {
DoUIChange3
DoUIChange4
}
If both blocks are executed on the main thread, then the actual
command stream is either:
DoUIChange1
DoUIChange2
DoUIChange3
DoUIChange4
or…
DoUIChange3
DoUIChange4
DoUIChange1
DoUIChange2
However, if both blocks are executed on their own threads, even more
possibilities open up:
DoUIChange3
DoUIChange1
DoUIChange2
DoUIChange4
or..
DoUIChange1
DoUIChange3
DoUIChange2
DoUIChange4
or..
DoUIChange1
DoUIChange3
DoUIChange4
DoUIChange2
etc…
Needless to say, if the UI code is at all complex the number of
combinations quickly becomes enormous, making unexpected UI bugs
basically unavoidable.