这篇文章总结iOS开发中用到的全部和定时器相关的内容,用到某个定时器就会总结一下,所以持续更新中~
CADisplayLink
CADisplayLink介绍
-
CADisplayLink
定时器在屏幕刷新时调用方法做事情。
CADisplayLink使用场景
- 根据其调用方法的时机的特点(屏幕刷新时调用),可以结合
setNeedDisplay
(调用drawRect
方法,drawRect
方法会在屏幕刷新时重绘屏幕的内容)实现很流畅的动画效果。
let displayLink = CADisplayLink(target: self, selector: #selector(update))
displayLink.add(to: RunLoop.main, forMode: RunLoopMode.commonModes)
func update() {
// 改变某个变量,实现移动内容的位置,实现动画效果
......
/*
* setNeedsDisplay方法在屏幕刷新时会调用drawRect方法
* 因为定时器CADisplayLink执行方法的时间(屏幕刷新时)和setNeedDisplay调用drawRect方法(屏幕刷新时重绘)的时间是一致的。所以动画会很流畅
* 适用的场景:二维码扫描的“扫描线”
*/
self.setNeedsDisplay()
}
Timer
概述
Timers结合RunLoop一起使用,RunLoop会强引用加入RunLoop的定时器,因此你不需要手动(比如通过属性的方式)强引用定时器。
如果想要高效的使用Timer,你需要了解RunLoop是如何工作的。点击Threading Programming Guide了解更多关于线程和RunLoop的信息。
Timer不是实时触发的机制,当一个Timer处在一个长时间循环RunLoop中或者当前RunLoop不是Timer加入的RunLoop时,定时器都有可能被延迟触发。当当前RunLoop正是Timer加入的RunLoop时,RunLoop会在每次运行循环时检查是否触发Timer
你可以在创建的时候,指定Timer是否重复触发。一个不重复触发的定时器触发一次后就会被自动销毁,以此防止定时器再一次触发。
相反,一个重复触发的定时器总是在新的一次RunLoop循环中重新根据RunLoop开始的时间设置自己的触发时间。而不是预计的时间。
简单来说就是,比如定时器理论上在10、15、20、25……被触发。第一次在第10秒触发,下一次因为某种原因(切换运行模式)延迟了,导致23秒才触发一次,相当于跳过15秒和20秒,那么如果再一次不被延迟,理论上是25秒触发,不会因为23秒触发一次,就导致变成28秒触发。
在iOS7和mac OS 10.0之后新增了一个Tolerance
属性,可以为定时器指定一个Tolerance(允许误差的时间,默认为0)。
这种允许误差带来的灵活性,当一个定时器触发时,提高了系统优化电量消耗和事件响应的能力。
定时器可以在预定的触发时间和预定触发时间加上Tolerance之间的任何时间触发。定时器不会在预定的时间之前触发。
当使用定时器的时候,Tolerance的值一般是时间间隔的10%,比如Timer每个5秒触发一次,那么Tolerance为1秒。即使Tolerance很小,也对系统的优化电源消耗能力有大的作用。
Timer的使用
创建定时的三种方式
-
init(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool)
通过这种方式创建的Timer需要手动添加到RunLoop中。 -
class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
通过这种方式创建Timer,Timer默认被添加到Default Mode。 -
public init(fireAt date: Date, interval ti: TimeInterval, target t: Any, selector s: Selector, userInfo ui: Any?, repeats rep: Bool)
通过这种方式创建的Timer需要手动添加到RunLoop中。
网友评论