Swift UI - 使用UIDatePicker实现倒计时功能

注:代码已升级至Swift4

如果使用UIDatePicker时将模式设置为CountDownTimer,即可让该控件作为倒计时器来使用。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import UIKit

class ViewController: UIViewController {

var ctimer:UIDatePicker!
var btnStart:UIButton!

var leftTime:Int = 180
var alertController:UIAlertController!

var timer:Timer!

override func viewDidLoad() {
super.viewDidLoad()

ctimer = UIDatePicker(frame:CGRect(x:0, y:120, width:200, height:200))
self.ctimer.datePickerMode = UIDatePickerMode.countDownTimer

//必须为60的整数倍,比如设置为100,值自动变为60
self.ctimer.countDownDuration = TimeInterval(leftTime)
ctimer.addTarget(self, action: #selector(ViewController.timerChanged),
for: .valueChanged)

self.view.addSubview(ctimer)

btnStart = UIButton(type: .system)
btnStart.frame = CGRect(x:100, y:400, width:100, height:100);
btnStart.setTitleColor(UIColor.red, for: .normal)
btnStart.setTitleColor(UIColor.green, for:.disabled)
btnStart.setTitle("开始", for:.normal)
btnStart.setTitle("倒计时中", for:.disabled)

btnStart.clipsToBounds = true
btnStart.layer.cornerRadius = 5
btnStart.addTarget(self, action:#selector(ViewController.startClicked),
for:.touchUpInside)

self.view.addSubview(btnStart)
}

@objc func timerChanged() {
print("您选择倒计时间为:\(self.ctimer.countDownDuration)")
}

/**
* 开始倒计时按钮点击
*/
@objc func startClicked(sender:UIButton) {
self.btnStart.isEnabled = false

// 获取该倒计时器的剩余时间
leftTime = Int(self.ctimer.countDownDuration);
// 禁用UIDatePicker控件和按钮
self.ctimer.isEnabled = false

// 创建一个UIAlertController对象(警告框),并确认,倒计时开始
alertController = UIAlertController(title: "系统提示",
message: "倒计时开始,还有 \(leftTime) 秒...",
preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "确定", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
// 显示UIAlertController组件
self.present(alertController, animated: true, completion: nil)

// 启用计时器,控制每秒执行一次tickDown方法
timer = Timer.scheduledTimer(timeInterval: TimeInterval(1), target:self,
selector:#selector(ViewController.tickDown),
userInfo:nil, repeats:true)
}

/**
* 计时器每秒触发事件
*/
@objc func tickDown() {
alertController.message = "倒计时开始,还有 \(leftTime) 秒..."
// 将剩余时间减少1秒
leftTime -= 1;
// 修改UIDatePicker的剩余时间
self.ctimer.countDownDuration = TimeInterval(leftTime);
print(leftTime)
// 如果剩余时间小于等于0
if (leftTime <= 0) {
// 取消定时器
timer.invalidate();
// 启用UIDatePicker控件和按钮
self.ctimer.isEnabled = true;
self.btnStart.isEnabled = true;
alertController.message = "时间到!"
}
}
}

问题解决

上面的代码其实还是有个小Bug的

  • 问题描述:代码中给时间控件添加了个 ValueChanged 事件监听响应,目的是想每次选择的时间改变时都会触发打印出时间。但运行会发现,第一次拨动表盘不触发,后面再改变值才会触发。

  • 解决办法:这个是iOS的bug,我们把设置初始时间代码

1
2
//必须为 60 的整数倍,比如设置为100,值自动变为 60
self.ctimer.countDownDuration = TimeInterval(leftTime)

修改成

1
2
3
DispatchQueue.main.async {
self.ctimer.countDownDuration = TimeInterval(self.leftTime)
}

如果我们不需要关心值改变事件的话,直接用原来的赋值方法即可

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :