今天給各位猿友說一下怎么使用GCD來實(shí)現(xiàn)倒計(jì)時(shí)的功能效果达皿,首先給大家簡單介紹一下實(shí)現(xiàn)的原理:使用GCD創(chuàng)建定時(shí)器并設(shè)置定時(shí)器的間隔時(shí)間為1秒,然后在定時(shí)器的響應(yīng)事件方法中將倒計(jì)時(shí)的總時(shí)間依次減1,由于定時(shí)器響應(yīng)事件是在block中红选,所有控件的修改需要使用__weak來修飾,避免循環(huán)調(diào)用。下面來給大家上代碼:
1粟矿、為了清晰的展示效果,先聲明一個(gè)button屬性
#import "ViewController.h"
@interface ViewController ()
//倒計(jì)時(shí)的button
@property (nonatomic, strong) UIButton * btn;
@end
聲明好之后需要實(shí)現(xiàn)璧针,創(chuàng)建該按鈕button并實(shí)現(xiàn)點(diǎn)擊響應(yīng)事件方法
#pragma mark - create button
- (void)createButton {
_btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 50)];
_btn.center = self.view.center;
_btn.backgroundColor = [UIColor orangeColor];
[_btn setTitle:@"獲取驗(yàn)證碼" forState:UIControlStateNormal];
[_btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_btn];
}
#pragma mark - button event
- (void)btnClick:(UIButton *)btn{
//點(diǎn)擊button 關(guān)閉可交互 背景顏色變?yōu)榛疑? _btn.userInteractionEnabled = NO;
_btn.backgroundColor = [UIColor grayColor];
//同時(shí)創(chuàng)建計(jì)時(shí)器 開始倒計(jì)時(shí)
[self createTimer];
}
2嚷炉、核心代碼就是使用GCD創(chuàng)建定時(shí)器并對UI操作
#pragma mark - 定時(shí)器 (GCD)
- (void)createTimer {
//設(shè)置倒計(jì)時(shí)時(shí)間
//通過檢驗(yàn)發(fā)現(xiàn)渊啰,方法調(diào)用后探橱,timeout會先自動-1申屹,所以如果從15秒開始倒計(jì)時(shí)timeout應(yīng)該寫16
//__block 如果修飾指針時(shí),指針相當(dāng)于弱引用隧膏,指針對指向的對象不產(chǎn)生引用計(jì)數(shù)的影響
__block int timeout = 16;
//獲取全局隊(duì)列
dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//創(chuàng)建一個(gè)定時(shí)器哗讥,并將定時(shí)器的任務(wù)交給全局隊(duì)列執(zhí)行(并行,不會造成主線程阻塞)
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, global);
// 設(shè)置觸發(fā)的間隔時(shí)間
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//1.0 * NSEC_PER_SEC 代表設(shè)置定時(shí)器觸發(fā)的時(shí)間間隔為1s
//0 * NSEC_PER_SEC 代表時(shí)間允許的誤差是 0s
//block內(nèi)部 如果對當(dāng)前對象的強(qiáng)引用屬性修改 應(yīng)該使用__weak typeof(self)weakSelf 修飾 避免循環(huán)調(diào)用
__weak typeof(self)weakSelf = self;
//設(shè)置定時(shí)器的觸發(fā)事件
dispatch_source_set_event_handler(timer, ^{
//倒計(jì)時(shí) 刷新button上的title 胞枕,當(dāng)?shù)褂?jì)時(shí)時(shí)間為0時(shí)杆煞,結(jié)束倒計(jì)時(shí)
//1. 每調(diào)用一次 時(shí)間-1s
timeout --;
//2.對timeout進(jìn)行判斷時(shí)間是停止倒計(jì)時(shí),還是修改button的title
if (timeout <= 0) {
//停止倒計(jì)時(shí)腐泻,button打開交互决乎,背景顏色還原,title還原
//關(guān)閉定時(shí)器
dispatch_source_cancel(timer);
//MRC下需要釋放派桩,這里不需要
// dispatch_realse(timer);
//button上的相關(guān)設(shè)置
//注意: button是屬于UI构诚,在iOS中多線程處理時(shí),UI控件的操作必須是交給主線程(主隊(duì)列)
//在主線程中對button進(jìn)行修改操作
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.btn.userInteractionEnabled = YES;
weakSelf.btn.backgroundColor = [UIColor orangeColor];
[weakSelf.btn setTitle:@"獲取驗(yàn)證碼" forState:UIControlStateNormal];
});
}else {
//處于正在倒計(jì)時(shí)铆惑,在主線程中刷新button上的title范嘱,時(shí)間-1秒
dispatch_async(dispatch_get_main_queue(), ^{
NSString * title = [NSString stringWithFormat:@"%d秒后重新獲取驗(yàn)證碼",timeout];
[weakSelf.btn setTitle:title forState:UIControlStateNormal];
});
}
});
dispatch_resume(timer);
}
OK!現(xiàn)在已經(jīng)實(shí)現(xiàn)了倒計(jì)時(shí)的效果员魏,代碼比較簡單丑蛤。由于小編還不太會錄演示視頻,下邊只能以圖片來簡單說明一下撕阎,相信聰明的我們都會理解是什么意思的受裹。
這是點(diǎn)擊按鈕前的樣式,按鈕可以被點(diǎn)擊闻书。
這是點(diǎn)擊按鈕之后的樣式名斟,進(jìn)入倒計(jì)時(shí)狀態(tài),按鈕不可被點(diǎn)擊魄眉。倒計(jì)時(shí)結(jié)束之后自動恢復(fù)為點(diǎn)擊之前的狀態(tài)砰盐。
相信這兩張圖片可以讓大家清晰的看到效果,最后還是希望能夠幫助有需要的猿友們坑律,如果有什么不足之處岩梳,還需要大家多多給出建議。愿同是程序猿的我們能夠共同學(xué)習(xí)進(jìn)步晃择,謝謝冀值!