Как вызвать метод a.s.a.p. но самое раннее в следующей итерации цикла выполнения? - PullRequest
16 голосов
/ 17 августа 2011

Мне нужен безопасный способ сказать: «iOS, я хочу, чтобы этот метод был выполнен как можно скорее, но НЕ в ЭТОЙ итерации цикла выполнения. В ближайшее время, но не в этом. Спасибо.»

Прямо сейчас я всегда делаю это так:

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

С предположением, что -doSomeOtherThings всегда будет выполняться ДО -doSomethingInNextRunLoop.

В документации сказано:

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

Таким образом, в принципе может случиться так, что метод вызывается немедленно, как если бы я только что отправил прямое сообщение, вызывая -doSomethingInNextRunLoop должен быть выполнен до -doSomeOtherThings?

Как я могу быть абсолютно уверен, что он будет вызван как можно скорее, но НИКОГДА никогда не будет в этой итерации цикла выполнения?

Чтобы уточнить формулировку: С циклом выполненияЯ имею в виду основной поток и итерацию, в которой все методы должны возвращаться, пока поток снова не будет готов к новым событиям.

Ответы [ 4 ]

9 голосов
/ 17 августа 2011

Если вы беспокоитесь о том, что Apple может когда-нибудь в специальном случае задержать 0, вы всегда можете указать задержку 1e-37 или около того.Хотя документацию для performSelector:withObject:afterDelay: можно легко прочитать, чтобы гарантировать, что селектор всегда будет запланирован для следующей итерации цикла выполнения.

Если вы беспокоитесь, что Apple может когда-нибудь сделать особыйВ случае, если задержка меньше некоторой произвольной нижней границы, вы всегда можете попробовать использовать performSelector:target:argument:order:modes: в NSRunLoop, который, как указано в документации, будет планировать выполнение для следующей итерации цикла выполнения.

6 голосов
/ 18 марта 2014

Довольно тривиально, используя GCD (Grand Central Dispatch):

dispatch_async (dispatch_get_main_queue (), ^{
    NSLog (@"This stuff runs in the next iteration of the main run loop");
});
1 голос
/ 17 августа 2011

Я думаю, вы пришли к выводу, что, прочитав документацию, вы ошиблись.

Так что в принципе может случиться так, что метод вызывается немедленно, как если бы я только что отправил прямое сообщение

Нет.В той части документации, которую вы цитируете, говорится, что селектор всегда ставится в очередь в цикле выполнения, несмотря ни на что.Так что оно никогда не будет выполнено просто как прямое сообщение.

Первое предложение с «необязательно» может быть немного вводящим в заблуждение, но я думаю, что второе предложение должно действительно прояснить, что то, чего вы боитесь, не подходитслучается.

0 голосов
/ 17 августа 2011

Конечно, вы просто делаете это;

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

Что гарантирует требуемый порядок выполнения.

...