Как -performSelector: withObject: afterDelay: работать?
В настоящее время я работаю в предположении, что -performSelector:withObject:afterDelay:
не использует потоки, но расписывает событие, которое будет запущено позднее в текущем потоке. Правильно ли это?
Подробнее, в частности:
- (void) methodCalledByButtonClick {
for (id obj in array) {
[self doSomethingWithObj:obj];
}
}
static BOOL isBad = NO;
- (void) doSomethingWithObj:(id)obj {
if (isBad) {
return;
}
if ([obj isBad]) {
isBad = YES;
[self performSelector:@selector(resetIsBad) withObject:nil afterDelay:0.1];
return;
}
//Do something with obj
}
- (void) resetIsBad {
isBad = NO;
}
Гарантируется ли, что -resetIsBad
не будет вызываться до тех пор, пока не вернется -methodCalledByButtonClick
, если мы будем работать в основном потоке, даже если -methodCalledByButtonClick
занимает сколь угодно длительное время для завершения?
Ответы
Ответ 1
Из docs:
Вызывает метод приемника текущий поток, используя значение по умолчанию после задержки.
Далее обсуждается:
Этот метод устанавливает таймер для выполнения сообщение aSelector на текущем цикл выполнения потоков. Таймер настроен для работы в режиме по умолчанию (NSDefaultRunLoopMode). Когда таймер огни, поток пытается удалить из очереди сообщение из цикла запуска и выполните селектор. Успешно, если выполняется цикл выполнения и в режим по умолчанию; в противном случае таймер ждет, пока цикл выполнения не будет по умолчанию.
Из этого мы можем ответить на ваш второй вопрос. Да, он гарантировал, даже с более короткой задержкой, так как текущий поток занят, когда вызывается performSelector
. Когда поток вернется в цикл выполнения и удалит селектор, вы вернетесь с вашего methodCalledByButtonClick
.
Ответ 2
performSelector:withObject:afterDelay:
планирует таймер в том же потоке, чтобы вызвать селектор после пройденной задержки. Если вы зарегистрируетесь в режиме запуска по умолчанию (т.е. Не используете performSelector:withObject:afterDelay:inModes:
), я уверен, что он будет ждать, пока следующий проход пройдет через цикл выполнения, поэтому все в стеке будет завершено первым.
Даже если вы вызываете с задержкой 0, он будет ждать следующего цикла и будет вести себя так, как вам нужно. Для получения дополнительной информации см. документы.