Как вызвать метод как можно скорее, но в ближайшее время в следующей итерации цикла выполнения?

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

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

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

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

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

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

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

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

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

4 ответа

Решение

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

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

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

dispatch_async (dispatch_get_main_queue (), ^{
    NSLog (@"This stuff runs in the next iteration of the main run loop");
});

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

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

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

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

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

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

Что гарантирует выполнение заказа вы хотите.

Другие вопросы по тегам