我目前正在假设-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>
答案 0 :(得分:45)
来自docs:
调用接收器的方法 当前主题使用默认值 延迟后的模式。
讨论更进一步:
此方法设置要执行的计时器 当前的aSelector消息 线程的运行循环。计时器是 配置为在默认模式下运行 (NSDefaultRunLoopMode)。当计时器 火灾,线程试图出列 来自运行循环的消息和 执行选择器。如果成功的话 运行循环正在运行并在 默认模式;否则,计时器 等到运行循环进入 默认模式。
从这里我们可以回答你的第二个问题。 是的,保证,即使延迟时间较短,因为当调用performSelector
时当前线程忙于执行。当线程返回到运行循环并使选择器出列时,您将从methodCalledByButtonClick
返回。
答案 1 :(得分:12)
performSelector:withObject:afterDelay:
在同一个线程上安排一个计时器,在传递的延迟后调用选择器。如果您注册默认运行模式(即不使用performSelector:withObject:afterDelay:inModes:
),我相信它会保证等到下一次通过运行循环,因此堆栈中的所有内容都将首先完成。
即使你以0的延迟调用,它也会等到下一个循环,并按照你的意愿行事。有关详细信息,请参阅the docs。