use*_*748 6 nstimer grand-central-dispatch ios swift
我的应用程序中目前有两个NSTimer计时器,它们负责获取数据和更新UI。最近我注意到,当计时器运行时,我的UI性能很差,例如,用户无法很好地滚动UITableview或根本无法滚动。我在其他地方读过,可以将计时器推入不同的运行循环中,这可能会有所帮助。这是我的计时器现在的样子:
let aSelector : Selector = "updateLocation"
timer = NSTimer.scheduledTimerWithTimeInterval(((NSUserDefaults.standardUserDefaults().stringForKey("mapUpdate")! as NSString).doubleValue), target: self, selector: aSelector, userInfo: nil, repeats: true)
Run Code Online (Sandbox Code Playgroud)
如何修改Swift计时器,使其在后台线程中运行?我一直在阅读,但一直感到困惑。
Ami*_*eza 12
如果计时器在主线程的运行循环上触发,则UI或计时器可能会出现问题。
例如,假设您触发了一个计时器。您的应用程序中还有一个tableView,它向用户显示一个列表,并且用户正在滚动表。同时,计时器的时间过去了。我们希望计时器的代码块可以立即执行,但是直到用户结束滚动操作才执行。在许多情况下,这不是我们想要的。
实际上,此问题以及您在问题中提到的问题的根源在于,您已经在主线程上运行了计时器,在该线程上,您的任务和所有UI操作都是按顺序处理的。串行表示仅在上一个任务完成时才执行一个任务。
为了解决这个问题,一种解决方案是在后台线程的运行循环上调用计时器,如下所示:
DispatchQueue.global(qos: .background).async {
let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: selector(fireTimer), repeats: false)
let runLoop = RunLoop.current
runLoop.add(timer, forMode: .defaultRunLoopMode)
runLoop.run()
}
Run Code Online (Sandbox Code Playgroud)
注意:如果您的计时器被重复调用,请不要忘记在任务结束时调用计时器的invalidate(),否则运行循环将对计时器的目标对象保持强烈的引用,这可能导致内存泄漏。
还有一个更好的选项来代替Timer类。您可以使用DispatchSourceTimer。
有关更多信息,请参考以下链接:
要在不同的运行循环上安排计时器,您可以使用:
// Create an unscheduled timer
let timer = NSTimer(
((NSUserDefaults.standardUserDefaults().stringForKey("mapUpdate")! as NSString).doubleValue),
target: self,
selector: "updateLocation",
userInfo: nil,
repeats: true)
// Add the timer to a runloop (in this case the main run loop)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
Run Code Online (Sandbox Code Playgroud)
请注意,我不确定这是否真正解决了您的问题,甚至不确定这是否是处理问题的好方法。从您的进一步讨论中,我想我可能会关注一些使用的东西CLLocationManager.startMonitoringSignificantLocationChanges,这将消除定期检查位置的需要,只需在它发生显着变化时进行更新,其中显着被适当定义。请注意,速度和航向可直接从 获取,CLLocation因此以精确的时间间隔更新并不重要。
| 归档时间: |
|
| 查看次数: |
6180 次 |
| 最近记录: |