Выполнить цикл следующего запуска: что не так с GCD?

Я пытаюсь использовать эти два подхода:

dispatch_async(dispatch_get_main_queue(),^{
    [self handleClickAsync];
});

и

[self performSelector:@selector(handleClickAsync) withObject:nil afterDelay:0];

в ответ на нажатие кнопки.

Вторая позволяет UIButton выделить, как можно было бы ожидать, и выполнить handleClickAsync в следующем цикле выполнения (я полагаю: "через некоторое время" ). Первый не позволяет экземпляру UIButton загореться, пока операция не будет полностью выполнена.

Каков правильный способ сделать это с помощью GCD или еще performSelector?

Ответ 1

Я считаю, что ответ найден здесь в обсуждении главной очереди отправки:

Эта очередь работает с циклом запуска приложений (если таковой имеется) для чередования выполнения задач с очередью с выполнением других источников событий, связанных с циклом выполнения.

Другими словами, основная очередь отправки устанавливает дополнительную очередь (наряду со стандартной очередью событий, предоставляемой UIApplicationMain() для обработки блоков, отправленных в основную очередь. Когда в очереди присутствуют блоки, цикл выполнения будет чередовать задачи выделения из основной очереди событий и очереди отправки. С другой стороны, reference для параметра delay -performSelector:withObject:afterDelay: отмечает, что:

Задание задержки 0 не обязательно приводит к немедленному выполнению селектора. Селектор по-прежнему поставлен в очередь на цикл выполнения потоков и выполняется как можно скорее.

Таким образом, когда вы используете селектор выполнения, операция ставится в очередь в конце основной очереди событий и не будет выполняться до тех пор, пока все перед ней в очереди (предположительно включая код, чтобы высвечивать UIButton) обработан. Однако, когда вы используете основную очередь отправки, он добавляет блок во вторичную очередь, которая затем, вероятно, сразу обрабатывается (т.е. В следующем цикле выполнения), предполагая, что в основной очереди нет других блоков. В этом случае код, чтобы высвечивать кнопку, по-прежнему находится в основной очереди событий, в то время как цикл выполнения обрабатывает событие из очереди вторичных блоков.

Ответ 2

Думаю, это поразит ваш момент:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
     //bla bla bla
}];