Что происходит при вызове dispatch_async на главной очереди
Что проверяют
Понимаете ли вы, что главная очередь последовательная и привязана к главному потоку, и чем «выполнить сейчас» отличается от «поставить в очередь». Это основа любой работы с интерфейсом: половина зависаний и странных морганий растёт отсюда.
Как отвечать
Асинхронная отправка кладёт блок в конец главной очереди и сразу возвращает управление. Блок выполнится на главном потоке, но не в текущей точке, а когда поток освободится и цикл выполнения дойдёт до очереди. Очередь последовательная, порядок строго тот, в котором блоки добавляли.
Отсюда два сценария:
- вызов с фонового потока: штатный способ вернуться к интерфейсу после сети или тяжёлого расчёта, ведь трогать вью можно только с главного потока;
- вызов уже с главного потока: блок не выполняется на месте, он откладывается на следующий проход цикла. Этим пользуются, когда нужно дождаться, пока система закончит раскладку или анимацию, и только потом померить размеры.
Стоит добавить, что синхронный вариант на главной очереди из самого главного потока это гарантированная взаимная блокировка: очередь ждёт, когда освободится поток, поток ждёт, когда выполнится блок. В коде на современном конкурентном API тот же смысл выражают изоляцией на главном акторе.
Где спотыкаются
Говорят, что задача уйдёт параллельно. Параллельности тут нет: очередь одна и поток один, блок просто встанет за текущей работой. Тяжёлый цикл внутри него повесит интерфейс точно так же, как если бы был написан напрямую.
Заворачивают в асинхронную отправку вообще всё, включая код, который уже и так на главном потоке. Обновление уезжает на кадр позже, пользователь успевает увидеть старое состояние; проверить поток и обновить на месте дешевле.
Считают, что отправка на главную очередь повышает приоритет или ускоряет показ. Она задаёт только поток выполнения и порядок. Если главный поток занят разбором большого ответа, блок прождёт ровно столько, сколько тот занят.