一般在项目的“引导页”有个功能,倒计时5秒结束后,然后可以允许用户点击跳过按钮跳过引导页。同样在“登录”和“注册”页面也有类似功能,发送验证码后,计时60秒后才允许用户再次请求重新发送验证码。
计时方式一(sleep + performSelector)
通过调用sleep(1)阻塞线程的方式来达到目的
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
|
import UIKit
class GAPublishViewController: GABaseViewController {
var jumpBut = UIButton(frame: CGRect(x: 15, y: 64, width: 80, height: 40));
var limitTime: Int = 5+1;
override func viewDidLoad() {
super.viewDidLoad()
setupJumpButton();
startCountDown();
}
func setupJumpButton() {
view.addSubview(jumpBut);
jumpBut.setTitle( "跳过(5S)" , for : .normal);
jumpBut.setTitleColor(UIColor.red, for : .normal);
jumpBut.addTarget(self, action: #selector(tapJumpAction(sender:)), for : .touchUpInside);
}
@objc func tapJumpAction(sender: Any) {
let but = sender as! UIButton;
let text = but.titleLabel?.text ?? "" ;
if (text == "跳过" ) {
print( "点击“跳过”" );
}
}
// MARK: 定时方式一
func startCountDown() {
performSelector(inBackground: #selector(countDownThread), with: nil)
}
@objc func countDownThread() {
let timeCount = limitTime;
for _ in 0..<timeCount {
limitTime = limitTime - 1;
self.performSelector(onMainThread: #selector(updateJumpBtn), with: self, waitUntilDone: true )
sleep(1);
}
}
@objc func updateJumpBtn() {
if (limitTime <= 0) {
jumpBut.setTitle( "跳过" , for : .normal);
} else {
jumpBut.setTitle( "跳过" + "(\(limitTime)S)" , for : .normal);
}
}
}
|
计时方式二(sleep + GCD)
与上面的方式一类似
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
|
// MARK: 定时方式二
func startCountDown() {
// 将任务添加到队列,以异步的方式执行
DispatchQueue.global().async { [weak self] in
self?.countDownThread();
}
}
func countDownThread() {
let timeCount = limitTime;
for _ in 0..<timeCount {
limitTime = limitTime - 1;
// 主线程刷新UI
DispatchQueue.main.async { [weak self] in
self?.updateJumpBtn();
}
sleep(1);
}
}
func updateJumpBtn() {
if (limitTime <= 0) {
jumpBut.setTitle( "跳过" , for : .normal);
} else {
jumpBut.setTitle( "跳过" + "(\(limitTime)S)" , for : .normal);
}
}
|
计时方式三(Timer)
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
|
// MARK: 定时方式三
var limitTime: Int = 5;
var timer: Timer?;
func startCountDown() {
// 初始化定时器
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateJumpBtn), userInfo: nil, repeats: true );
/*
// 避免timer在列表时,滑动时timer会暂停。 将timer放在另外一个线程中,然后开启这个线程的runloop。
DispatchQueue.global().async { [weak self] in
self?.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self as Any, selector: #selector(self?.countDownThread), userInfo: nil, repeats: true);
RunLoop.current.run();
}
*/
}
@objc func countDownThread() {
// 主线程刷新UI
DispatchQueue.main.async { [weak self] in
self?.updateJumpBtn();
}
}
@objc func updateJumpBtn() {
limitTime = limitTime - 1;
if (limitTime <= 0) {
jumpBut.setTitle( "跳过" , for : .normal);
/*
// 暂停定时器
timer?.fireDate = Date.distantFuture;
// 继续定时
timer?.fireDate = NSDate.init() as Date;
// 暂停定时器3秒
timer?.fireDate = Date.init(timeIntervalSinceNow: 3.0);
*/
// 停止定时器
timer?.invalidate();
} else {
jumpBut.setTitle( "跳过" + "(\(limitTime)S)" , for : .normal);
}
}
|
计时方式四(GCD)
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
|
// MARK: 定时方式四
var limitTime: Int = 5+1;
// 在global线程里创建一个时间源
let codeTimer = DispatchSource.makeTimerSource(queue: DispatchQueue.global());
func startCountDown() {
// 设定这个时间源是每秒循环一次,立即开始
codeTimer.schedule(deadline: .now(), repeating: .seconds(1));
// 设定时间源的触发事件
codeTimer.setEventHandler(handler: {
// 主线程刷新UI
DispatchQueue.main.async { [weak self] in
self?.updateJumpBtn();
}
})
// 判断是否取消,如果已经取消了避免调用resume()方法导致的崩溃
if codeTimer.isCancelled {
return ;
}
// 启动时间源
codeTimer.resume();
}
func updateJumpBtn() {
limitTime = limitTime - 1;
if (limitTime <= 0) {
jumpBut.setTitle( "跳过" , for : .normal);
// 暂停计时。暂停之后,再次开始计时(startCountDown())接着上次暂停进行计时
codeTimer.suspend();
// 取消计时。取消之后,再次开始计时(startCountDown())不会再计时
//codeTimer.cancel();
} else {
jumpBut.setTitle( "跳过" + "(\(limitTime)S)" , for : .normal);
}
}
|
示意图
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/wsyx768/article/details/104557048