I am new to swift and have been working my first application for a while now. During testing I have seen some crashes in my code and I believe they are caused by some of the UI updates not being processed on the main thread. I googled around and I read all "UI Updates" need to be made on the main thread. Will someone please confirm what exactly a "UI update" actually is for me?
Do I need to wrap all of the following inside "DispatchQueue.main.async" ?
- updating text in a TextView
- updating a UIButton text
- adding corner radius and button width values to a UIButton
- everytime I want to present an alert message
- each time I call "dismiss(animated: true, completion: nil)" to close the current ViewController and return to the previous one
- each time I call "storyBoard.instantiateViewController(withIdentifier: )" to create a ViewController and also when calling "present( )"
- updating the myLabel.frame.size values (width and height)
- updating a scrollview.frame.size value
- when the "isHidden" property of a button, label, etc is set
- setting colors to labels, buttons, etc.
In my viewDidLoad( ), viewWillLayoutSubviews( ), viewDidLayoutSubviews( ), etc. functions I hide objects, set borders, set colors, set ScrollView sizes, etc.. so would I use "DispatchQueue.main.async" inside all of these functions?
I do a bunch of UI updates (I believe) so wanted to understand whether I need to add a ton of separate "DispatchQueue.main.async" wrappers all over my code. It seems I would need plenty and I am concerned about polluting my code, where all you see is a ton of "DispatchQueue.main.async" wrappers all over the place.
Does my application start off using the main thread and then for some reason goes into the background thread? if so, then perhaps I would only need to use Dispatch in cases where my application would switch to the background thread? I would not know when this would occur of course.
I am also concerned that if I use "async" throughout my code then the code inside the Dispatch region will not execute right then but rather continue on executing the code located after/outside the dispatch region, whcih would be out of order as I would like the code to execute.
Perhaps someone can confirm all of this for me?
ASIDE
I tried using a DispatchQueue.main.async code wrapper around some code which updates label and button text. I confirmed the code inside the Dispatch region occasionally does not execute. I see the print statements which are before and after the Dispatch region but sometimes(occasionally) the print statements inside the region do not get hit. Should I be using "sync" instead of "async" to guarantee by code always runs when I want it to?
It is possible. But you can't just blindly "wrap" code in an async dispatch. Those are "asynchronous". You aren't "wrapping" the code. That is just an artifact of how you are expressing behaviour in the language. What you are doing is appending a block of code to a queue to be executed "later". It could be the same thread or a different thread. It could execute right away or after a few milliseconds. The code that follows it cannot assume that the dispatched block either has or has not run. You can do a sync dispatch, but that can be even trickier.
Performing actions in a delegate callback can also be tricky. That may be a case where dispatching onto the main thread is the correct solutions. I don't know. Sometimes it does work that way.