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

发布于 2024-11-23 15:28:06 字数 956 浏览 2 评论 0原文

可能的重复:
UIScrollView 暂停 NSTimer 直到滚动完成

我很难弄清楚为什么当我在 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];
}

Possible Duplicate:
UIScrollView pauses NSTimer until scrolling finishes

I am having a bit of trouble figuring out why the NSTimer stops as soon as I scroll in the UIWebView. Please take a look at the following code (I know this isn't a homework site, but I honestly am stuck):

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黄昏下泛黄的笔记 2024-11-30 15:28:06

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

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

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

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

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

You have to add the timer to another RunLoopMode. Per default a timer is added to the NSDefaultRunLoopMode. That means that the timer is only executing when the app’s run loop is in NSDefaultRunLoopMode.

Now, when a user touches the screen (e.g. to scroll a UIScrollView) the run loop’s mode will be switched to NSEventTrackingRunLoopMode. And now, that the run loop is not in NSDefaultRunMode anymore, the timer will not execute. The ugly effect of that is, that timer is blocked whenever the user touches the screen. And that can be a looong time when the user is scrolling, because the timer is blocked until the scrolling completely stops. And when the user continues to scroll, the timer is blocked again.

Fortunately the solution to this problem is quite simple: You can add your timer to another NSRunLoopMode. When add the timer to NSRunLoopCommonModes it will execute in all run loop modes (that have been declared as a member of the set of “common” modes, to be precise). That means that the timer is not only working in NSDefaultRunLoopMode but also in NSEventTrackingRunLoopMode (when the user touches the screen).

So after you initialize your timer, add it to NSRunLoopCommonModes:

[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
梅窗月明清似水 2024-11-30 15:28:06

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

如果您希望无论用户交互如何都调用计时器,则应考虑生成一个新线程并将计时器附加到该线程。

您还可以查看 基于 GCD Mike Ash 的计时器 将在后台运行。您唯一应该记住的是 UI 更新必须在主线程上完成。

Well user interaction blocks the main thread so the timer is delayed as it adds itself to the current thread's run loop.

If you want the timer to be called irrespective of user interaction, you should consider spawning a new thread and attaching the timer to that thread.

You can also look at a GCD based timer by Mike Ash which will run in the background. The only thing you should remember is that the UI updates must be done on the main thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文