如何将计时器移到后台线程 [英] How to Move Timer to Background Thread

查看:167
本文介绍了如何将计时器移到后台线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序中目前有两个NSTimer计时器,它们负责获取数据和更新UI.最近我注意到,当计时器运行时,我的UI性能很差,例如,用户无法很好地滚动UITableview或根本无法滚动.我在其他地方读过,可以将计时器推入不同的运行循环中,这可能会有所帮助.这是我的计时器现在的样子:

I currently have two NSTimer timers in my app that are responsible for taking data and updating the UI. I have noticed recently that while the timers are running I have poor UI performance, for example the user can't scroll through my UITableview well or at all. I've read elsewhere that it is possible to push the timers into a different runloop and that this could help. This is what my timer looks like now:

let aSelector : Selector = "updateLocation"
timer = NSTimer.scheduledTimerWithTimeInterval(((NSUserDefaults.standardUserDefaults().stringForKey("mapUpdate")! as NSString).doubleValue), target: self, selector: aSelector, userInfo: nil, repeats: true)

如何修改Swift计时器,使其在后台线程中运行?我一直在阅读,但一直感到困惑.

How can I modify my Swift timer such that it runs in a background thread? I've been reading about it but have been getting confused.

推荐答案

如果在主线程的运行循环中触发了计时器,则计时器功能或UI操作可能会出现问题.

If a timer is fired on the main thread's run loop, you will probably have a problem with either the timer function or UI operation.

例如,假设您触发了一个计时器.您的应用程序中还有一个tableView,它向用户显示一个列表,并且用户正在滚动表.同时,计时器的时间过去了.我们希望计时器的代码块可以立即执行,但是直到用户结束滚动操作才执行.在很多情况下,这不是我们想要的.

For example, suppose you have triggered a timer. There is also a tableView in your app that shows a list to the user and the user is scrolling the table. Meanwhile, the timer's time elapses. We expect that the code block of the timer executes immediately, but it doesn't until the user ends the scroll operation. In many cases, this isn't what we want.

此问题和您在问题中提到的问题的根源在于,您已经在主线程上运行了计时器,在该线程上,您的任务和所有UI操作都是按顺序处理的.串行表示仅在上一个任务完成时才执行一个任务.

The source of this problem and the problem you mentioned in your question is the fact that you have run the timer on the main thread, where your task and all UI operations are handled serially. serial means one task is executed only if the previous task finished.

为解决这个问题,一种解决方案是在后台线程的运行循环上调用计时器,如下所示:

To solve that, one solution is to call timers on a background thread's run loop like below:

DispatchQueue.global(qos: .background).async {
        Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { _ in
            print("After 3 seconds in the background")
        }
        RunLoop.current.run()
    }

ScheduledTimer方法创建一个计时器并将其安排在当前运行循环中.以下代码具有相同的含义:

The scheduledTimer method creates a timer and schedules it on the current run loop. The following code has the same meaning:

DispatchQueue.global(qos: .background).async {
        let timer = Timer(timeInterval: 6, repeats: false) { _ in
            print("After 6 seconds in the background")
        }
        let runLoop = RunLoop.current
        runLoop.add(timer, forMode: .default)
        runLoop.run()
    }

注意:如果您的计时器被重复调用,请不要忘记在任务结束时调用计时器的invalidate(),否则运行循环将保留对计时器目标对象的强大引用.在内存泄漏中.

Notice: if your timer is called repeatedly, don't forget to call invalidate() of the timer at the end of the task, otherwise the run loop will keep a strong reference to the target object of the timer that could result in memory leak.

还有一个更好的选择,而不是Timer类.您可以使用DispatchSourceTimer.

There is also a better option instead of the Timer class. You can use DispatchSourceTimer.

有关更多信息,请参见以下链接:

For more info refer to the following links:

  • The Secret World of Timer written by Danielle Margutti.
  • A Background Repeating Timer in Swift written by Daniel Galasko.

这篇关于如何将计时器移到后台线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆