为什么在UIWebView iPhone中滚动时计时器停止?

时间:2011-07-13 18:51:08

标签: iphone cocoa-touch uiwebview nstimer

  

可能重复:
  UIScrollView pauses NSTimer until scrolling finishes

当我在UIWebView中滚动时,我很难弄清楚为什么NSTimer会停止。请看下面的代码(我知道这不是一个家庭作业网站,但老实说我被困了):

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *address = @"http://en.m.wikipedia.org/wiki/";
    NSURL *url = [NSURL URLWithString:address];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [wiki loadRequest:request];
    time = 0;
    countValue = 0;
    timer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector: @selector(updateTimer) userInfo: nil repeats: YES];
    timeRand = 0;
    countValueRand = 1;
    randomTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector: @selector(updateRandomTimer) userInfo: nil repeats: YES];
    [self generateWordsArray];
}

2 个答案:

答案 0 :(得分:30)

您必须将计时器添加到另一个RunLoopMode。默认情况下,计时器将添加到NSDefaultRunLoopMode。这意味着定时器仅在应用程序的运行循环位于NSDefaultRunLoopMode时执行。

现在,当用户触摸屏幕(例如滚动UIScrollView)时,运行循环的模式将切换到NSEventTrackingRunLoopMode。现在,运行循环不再在NSDefaultRunMode中,计时器将不会执行。其丑陋的效果是,只要用户触摸屏幕,该计时器就会被阻止。当用户滚动时,这可能是一个漫长的时间,因为计时器被阻止,直到滚动完全停止。当用户继续滚动时,计时器再次被阻止。

幸运的是,这个问题的解决方案非常简单:您可以将计时器添加到另一个NSRunLoopMode。将计时器添加到NSRunLoopCommonModes时,它将在所有运行循环模式中执行(确切地说,已声明为“常用”模式集的成员)。这意味着计时器不仅可以在NSDefaultRunLoopMode中工作,还可以在NSEventTrackingRunLoopMode中工作(当用户触摸屏幕时)。

因此,在初始化计时器后,将其添加到NSRunLoopCommonModes:

[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

答案 1 :(得分:1)

用户交互很好地阻塞了主线程,因此定时器会延迟,因为它会将自身添加到当前线程的运行循环中。

如果您希望调用计时器而不考虑用户交互,则应考虑生成新线程并将计时器附加到该线程。

您还可以查看将在后台运行的 Mike Ash GCD based timer。您应该记住的唯一事情是UI更新必须在主线程上完成。