Как делает-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 произвольно занимает много времени для завершения?

32
задан Ed Marty 17 December 2009 в 15:29
поделиться

2 ответа

Из docs :

Вызывает метод получателя на текущий поток с использованием значения по умолчанию режим после задержки.

Обсуждение продолжается дальше:

Этот метод устанавливает таймер для выполнения сообщение aSelector на текущем цикл выполнения потока. Таймер настроен для работы в режиме по умолчанию (NSDefaultRunLoopMode). Когда таймер срабатывает, поток пытается исключить из очереди сообщение из цикла выполнения и выполнить селектор. Успешно, если цикл выполнения работает и в режим по умолчанию; в противном случае таймер ждет, пока цикл выполнения не окажется в режим по умолчанию.

Отсюда мы можем ответить на ваш второй вопрос. Да, это гарантировано , даже с более короткой задержкой, поскольку текущий поток занят выполнением, когда вызывается performSelector . Когда поток вернется в цикл выполнения и удалит селектор из очереди, вы вернетесь из своего methodCalledByButtonClick .

45
ответ дан 27 November 2019 в 20:39
поделиться

performSelector: withObject: afterDelay: планирует таймер в том же потоке для вызова селектора после прошедшей задержки. Если вы зарегистрируетесь в режиме выполнения по умолчанию (то есть не используйте performSelector: withObject: afterDelay: inModes: ), я считаю, что он гарантированно дождется следующего прохода через цикл выполнения, поэтому все на стек завершится первым.

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

12
ответ дан 27 November 2019 в 20:39
поделиться