Как работает -performSelector: withObject: afterDelay:? - PullRequest
32 голосов
/ 17 декабря 2009

В настоящее время я работаю в предположении, что -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 занимает произвольно много времени для завершения?

Ответы [ 2 ]

45 голосов
/ 17 декабря 2009

Из документов :

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

Обсуждение идет дальше:

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

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

12 голосов
/ 17 декабря 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...