Как вызвать метод a.s.a.p. но не раньше следующей итерации цикла выполнения?

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

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

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

При условии, что -doSomeOtherThings всегда будет выполняться ПЕРЕД -doSomethingInNextRunLoop.

В документации говорится:

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

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

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

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


person openfrog    schedule 17.08.2011    source источник


Ответы (4)


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

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

person Anomie    schedule 17.08.2011
comment
Превосходно! Категория для облегчения этого имела бы смысл. - person openfrog; 18.08.2011

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

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

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

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

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

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

person w-m    schedule 17.08.2011
comment
Надеюсь, вы правы, потому что, держу пари, многие люди зависят от того, стоит ли он в очереди на следующую итерацию. И все же есть некоторая неопределенность. - person openfrog; 18.08.2011

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

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

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

person Roger    schedule 17.08.2011
comment
Не всегда удобно (или возможно) перестраивать код таким образом в случаях более сложных, чем этот тривиальный пример, приведенный для иллюстрации. - person Anomie; 18.08.2011
comment
Не совсем. Есть веские причины для выполнения действий в итерации цикла выполнения NEXT. Один из них: позволять пользовательскому интерфейсу обновляться между ними. Улучшение воспринимаемой производительности. Среди многих других. Кроме того, Аноми права. - person openfrog; 18.08.2011
comment
Конечно, ответ от Anomie попадает в точку, я просто указываю, что в некоторых случаях перестановка кода также может решить проблему. Немного похоже на писательский блок, иногда разработчики зацикливаются на решении проблемы определенным образом, когда на самом деле есть боковой план B. FWIW Я не знаю НИ ОДНОГО случая, когда стандартный PerformSelector:withObject:afterDelay:0 приводит к блокировать и часто использовать эту технику для оптимизации кода пользовательского интерфейса, написанного другими. - person Roger; 18.08.2011