倒计时功能在App中应用非常常见,例如启动微博启动页面的按钮,或者获取验证码计时,这里主要实现倒计时的基本功能
设计思路
- 计时器:Timer
- 触发计时器
- 显示载体:UILabel
通过点击Label触发计时器开始计时,每一秒改变Label的问题,实现倒计时的效果
核心代码
override func viewDidLoad() {
super.viewDidLoad()
countDownLabel.text = "获取验证码"
countDownLabel.backgroundColor = .gray
// 激活Label点击功能,并添加手势,否则无法点击
countDownLabel.isUserInteractionEnabled = true
// 点击Label调用 startTimer 函数
let tap = UITapGestureRecognizer(target: self, action: #selector(startTimer))
countDownLabel.addGestureRecognizer(tap)
}
func startTimer() {
// 每个一秒调用 updateTime 函数
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
//激活计时器
// Causes the timer's message to be sent to its target.
timer.fire()
}
func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
官方对于各个参数的解释
ti
: The number of seconds between firings of the timer. If ti is less than or equal to 0.0, this method chooses the nonnegative value of 0.1 milliseconds instead.
target
: The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to target until it (the timer) is invalidated.
aSelector
: The message to send to target when the timer fires.
userInfo
: The user info for the timer. The timer maintains a strong reference to this object until it (the timer) is invalidated. This parameter may be nil.
repeats
: If true, the timer will repeatedly reschedule itself until invalidated. If false, the timer will be invalidated after it fires.
func updateTime() {
count = count - 1
countDownLabel.text = "\(count)s"
countDownLabel.isUserInteractionEnabled = false
countDownLabel.backgroundColor = .lightGray
if count == 0 {
timer.invalidate()
countDownLabel.text = "获取验证码"
countDownLabel.isUserInteractionEnabled = true
countDownLabel.backgroundColor = .gray
count = 10
}
}
- 经过以上几行简单的代码既可以实现一个粗糙的倒计时器,效果如下
现有问题
但是请仔细看,倒计时的过程中,Label会出现闪烁的情况
为了便于观察我为Lable添加了一个背景色
这是一个由字体引起的问题,在iOS 9以后,系统默认的英文字体变为了San Fransico,这个字体的每个数字宽度都不相等
解决方法
- 替换字体
用每个数字宽度相同的字体代替默认字体,如Helvetica
countDownLabel.font = UIFont(name: "Helvetica", size: 26)
- 调用UIFont新的API使数字宽度一致
countDownLabel.font = UIFont.monospacedDigitSystemFont(ofSize: 26, weight: .regular)
以上两种方法皆可以解决Label闪烁的问题
这是对字体处理之后的效果,可以看到并不会想之前那样出现闪烁的情况
尊重原创,转载请注明出处,谢谢!
项目源码
网友评论