I have been using DispatchQueue.main.async for a long time to perform UI related operations.
Swift provides both DispatchQueue.main.async
sync or async methods have no effect on the queue on which they are called.
sync will block the thread from which it is called and not the queue on which it is called. It is the property of DispatchQueue which decides whether the DispatchQueue will wait for the task execution (serial queue) or can run the next task before current task gets finished (concurrent queue).
So even when DispatchQueue.main.async is an async call, a heavy duty operation added in it can freeze the UI as its operations are serially executed on the main thread. If this method is called from the background thread, control will return to that thread instantaneously even when UI seems to be frozen. This is because async call is made on DispatchQueue.main