13

我试图让我的应用程序在延迟后执行一个操作,但必须在用户与UIScrollView.

我不确定为什么两者都不会performSelector:withObject:afterDelayscheduledTimerWithTimeInterval:target:selector:userInfo:repeats:不会开火。是因为他们在后台线程上吗?

有什么建议或帮助吗?

4

3 回答 3

24

两者NSTimer并且performSelector:withObject:afterDelay:默认情况下仅在正常运行循环模式下触发。滚动时,运行循环处于事件跟踪模式。

您必须在所有常见模式下安排定时操作:

NSTimer *timer = [NSTimer timerWithTimeInterval:0.016 target:self selector:@selector(fire:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

或者

[self performSelector:@selector(fire:) withObject:nil afterDelay:1.0 inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];

还有专用的NSEventTrackingRunLoopMode

于 2012-06-28T21:07:41.233 回答
4

确保延迟触发发生在NSRunLoopCommonModes. 默认值是NSDefaultRunLoopMode在滚动时不会收到消息。

[self performSelector:@selector(fire:) withObject:nil afterDelay:2.0 inModes:@[NSRunLoopCommonModes]];

或者,您可以使用GCDwhich 也以相同的方式运行(不确定它使用哪种运行循环模式)

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    <#code to be executed on the main queue after delay#>
});
于 2013-05-15T08:06:39.087 回答
0

对于斯威夫特:

performSelector(#selector(fire:), withObject: sender, afterDelay: 1.0, inModes: [NSRunLoopCommonModes])
于 2016-07-22T09:56:38.260 回答