-performSelector:withObject:afterDelay:work?

Ed *_*rty 32 iphone cocoa-touch objective-c

我目前正在假设-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;
}
Run Code Online (Sandbox Code Playgroud)

假设我们在主线程上运行,即使需要任意长的时间来完成,它是否保证-resetIsBad-methodCalledByButtonClick返回之后才会被调用-methodCalledByButtonClick

Ben*_*n S 45

来自文档:

在延迟之后使用默认模式在当前线程上调用接收器的方法.

讨论更进一步:

此方法设置一个计时器,以在当前线程的运行循环上执行aSelector消息.计时器配置为以默认模式(NSDefaultRunLoopMode)运行.当计时器触发时,线程会尝试将消息从运行循环中出列并执行选择器.如果运行循环正在运行且处于默认模式,它会成功; 否则,计时器等待直到运行循环处于默认模式.

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


Ash*_*unn 12

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

即使你以0的延迟调用,它也会等到下一个循环,并按照你的意愿行事.有关更多信息,请参阅文档.