iOS开发中经常需要使用计时器。比如验证码倒计时等,所以今天总结一下iOS的计时器操作。
NSTimer 计时器
NSTimer是常用的计时器方案,主要是可以简单快速的创建一个Timer对象来进行操作。官方API如下:
// 创建方法1
open class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
// 创建方法2
public init(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool)
// 销毁方法。销毁之后要将Timer对象设置为nil。
open func invalidate()
虽然 NSTimer 是很常用的计时器,但是 NSTimer 如果和 ScrollView 同时使用的情况下,会造成 ScrollView 滑动时 Timer 停止运行,原因是 NSTimer 和 ScrollView 不在同一个 RunloopMode 下造成的。解决 ScrollView 和 Timer 冲突的方案为,将 NSTimer 加入到 Runloop 的 CommonModes 中。实例代码如下:
RunLoop.current.add(timer, forMode: RunLoop.Mode.common)
GCD 计时器
GCD 计时器和 Timer 计时器一样也是常用的一种计时器。Timer 计时器在运行时受 Runloop 的影响,但是 GCD 计时器不受 Runloop 的影响,可以让计数更加准确。
GCD 计时器示例代码如下:
var timer: DispatchSourceTimer?
...
var count = 1
timer = DispatchSource.makeTimerSource(flags: [], queue: nil)
timer?.schedule(deadline: .now(), repeating: 1)
timer?.setEventHandler {
print("count = \(count)")
count += 1
if count >= 60 {
self.timer?.cancel() // 停止计时器
}
}
timer?.resume()
CADisplayLink
CADisplayLink 是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。在应用中创建一个 CADisplayLink 对象,将CADisplayLink对象添加到 Runloop 中后,计时器就会启动,执行了 invalidate
函数之后。CADisplayLink 对象就会从 Runloop 中移除,selector 也会停止调用。
示例代码如下:
link = CADisplayLink(target: self, selector: #selector(countDown))
link?.preferredFramesPerSecond = 1 // 间隔时间
link!.add(to: RunLoop.current, forMode: .default) // 添加到 Runloop