-performSelector:withObject:afterDelay:work?

时间:2009-12-17 15:29:05

标签: iphone objective-c cocoa-touch

我目前正在假设-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需要任意长时间才能完成?< / p>

2 个答案:

答案 0 :(得分:45)

来自docs

  

调用接收器的方法   当前主题使用默认值   延迟后的模式。

讨论更进一步:

  

此方法设置要执行的计时器   当前的aSelector消息   线程的运行循环。计时器是   配置为在默认模式下运行   (NSDefaultRunLoopMode)。当计时器   火灾,线程试图出列   来自运行循环的消息和   执行选择器。如果成功的话   运行循环正在运行并在   默认模式;否则,计时器   等到运行循环进入   默认模式。

从这里我们可以回答你的第二个问题。 是的,保证,即使延迟时间较短,因为当调用performSelector时当前线程忙于执行。当线程返回到运行循环并使选择器出列时,您将从methodCalledByButtonClick返回。

答案 1 :(得分:12)

performSelector:withObject:afterDelay:在同一个线程上安排一个计时器,在传递的延迟后调用选择器。如果您注册默认运行模式(即不使用performSelector:withObject:afterDelay:inModes:),我相信它会保证等到下一次通过运行循环,因此堆栈中的所有内容都将首先完成。

即使你以0的延迟调用,它也会等到下一个循环,并按照你的意愿行事。有关详细信息,请参阅the docs