objective-c -performSelector:withObject:afterDelay: 如何工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1922517/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 22:37:44  来源:igfitidea点击:

How does -performSelector:withObject:afterDelay: work?

iphoneobjective-ccocoa-touch

提问by Ed Marty

I am currently working under the assumption that -performSelector:withObject:afterDelay:does not utilize threading, but schedules an event to fire at a later date on the current thread. Is this correct?

我目前的工作假设-performSelector:withObject:afterDelay:不使用线程,而是安排一个事件在当前线程的稍后日期触发。这样对吗?

More, specifically:

进一步来说:

- (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;
}

Is it guaranteed that -resetIsBadwill not be called until after -methodCalledByButtonClickreturns, assuming we are running on the main thread, even if -methodCalledByButtonClicktakes an arbitrarily long time to complete?

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

回答by Ben S

From the docs:

文档

Invokes a method of the receiver on the current threadusing the default mode after a delay.

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

The discussion goes further:

讨论更进一步:

This method sets up a timer to perform the aSelector message on the current thread's run loop. The timer is configured to run in the default mode (NSDefaultRunLoopMode). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.

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

From this we can answer your second question. Yes, it's guaranteed, even with a shorter delay since the current thread is busy executing when performSelectoris called. When the thread returns to the run loop and dequeues the selector, you'll have returned from your methodCalledByButtonClick.

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

回答by Asher Dunn

performSelector:withObject:afterDelay:schedules a timer on the same thread to call the selector after the passed delay. If you sign up for the default run mode (i.e. don't use performSelector:withObject:afterDelay:inModes:), I believe it is guaranteed to wait until the next pass through the run loop, so everything on the stack will complete first.

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

Even if you call with a delay of 0, it will wait until the next loop, and behave as you want here. For more info refer to the docs.

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