在 iOS 开发中,我们经常会用到 Timer 这个类,用来进行一些重复或者延迟调用。
不过,在实际的使用中,如果你是用来周期地更新 UI,则会发现 Timer 的调用经常会被其他操作阻挡导致无法正常更新 UI。
比如说在我的 HourlyMeow 项目中,自定义时钟界面要实现一个钟表供用户对时,这个电子表我就是用 Timer 实现的,由于是精确到秒,那么 TableView 滚动的时候就无法正确更新。
根本原因
默认来说,我们添加的 Timer 就自动加入了当前 RunLoop 的默认模式,这个 RunLoop 自然也就是主线程的 RunLoop ,但接下来你拖拽屏幕就不行了,因为 RunLoop 模式切换了!它切换到了一个专门用来响应拖拽的模式里,这样一来,你的 Timer 自然就无法更新 UI 了。
显然,这就是 Timer 阻挡主线程的根本原因,那么我们只要想办法把这个 Timer 也放到 RunLoop 的其他模式里不就可以了。
但是很遗憾,同一时间,一个 RunLoop 只可以运行一个模式,如果要变,就只能切换。——没错,它只有一个“线程”!运行了这个模式,那另一个就要停下来。
commonModes 从名字你就可以看出,它是一个复数,这实际上并不是一个真正的 RunLoop 模式,实际上是多个模式的集合,我们将 Timer 放到这个模式里,它也就在所有模式里生效。这样一来,无论你怎么操作手机,切换哪个 RunLoop 模式, Timer 也能正常调用了。
1 2 |
self.timer = Timer(timeInterval: 1, target: self, selector: #selector(updateTimeLabel), userInfo: nil, repeats: true) RunLoop.main.add(timer!, forMode: .commonModes) |
本文由 落格博客 原创撰写:落格博客 » Timer 无法在拖动时更新 UI
转载请保留出处和原文链接:https://www.logcg.com/archives/3046.html