Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WatchOS: Should UI updates from the extension be called on the main thread?

For iOS apps, UI updating is done from the main thread exclusively - not doing so is never recommended and can lead to unexpected behaviour.

In watchOS, the OS is structured with a watch extension, and an app - as different 'containers'. Usually, UI updates are called from the extension, and these update something in the app's container.

Does the same main thread logic apply to updating UI from the watch extension, or can UI updates be called from the background?


Edit - to bring some clarity. From the app's container, UI updates should probably happen on the main thread (as happens in most systems/OSs, as pointed out below). The question is really whether watchOS handles that for us, i.e. whether calling a UI update on the background thread of the extension will automatically be posted to the main thread of the app's container for us.

like image 480
Jordan Smith Avatar asked Feb 07 '16 23:02

Jordan Smith


2 Answers

Apple's App Programming Guide for watchOS would probably be the definitive guide, but I can find no reference in there regarding doing UI updates on threads other than the main thread.

One would think that if it was important that UI updates be be called from the main thread, that it would explicitly state that somewhere (as it does in the App Programming Guide for iOS, in the Threads and Concurrency section):

Work involving views, Core Animation, and many other UIKit classes usually must occur on the app’s main thread. There are some exceptions to this rule—for example, image-based manipulations can often occur on background threads—but when in doubt, assume that work needs to happen on the main thread.

Though, the above quote could be construed to be true of to UI updates to a Watch extension also, since that's running on iOS.

All of the above to say, I don't believe there's any Apple documentation stating one way or the other.

Here's another data point, though: Apple's Lister sample code now includes a WatchKit extension, and from my brief studying of it, it appears to be dispatching fetches to a background queue (see ListInfo.swift: 34) and updating the UI by dispatching back to the main queue (ListsInterfaceController.swift: 98). There's even a comment in there saying it's doing that:

The fetchInfoWithCompletionHandler(_:) method calls its completion handler on a background queue, dispatch back to the main queue to make UI updates.

I think based on the above, I'd err on the side of doing updates on the main thread, unless you determine there are performance or other implications of doing so.

like image 199
zpasternack Avatar answered Nov 13 '22 10:11

zpasternack


After contacting Apple through a Technical Support Incident, the received answer and explanation is below.

TLDR: use the main thread.

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.

like image 36
Jordan Smith Avatar answered Nov 13 '22 11:11

Jordan Smith