iOS定時(shí)器(時(shí)間不在于你擁有多少敦姻,而在于你怎樣使用)

開(kāi)篇

很喜歡某個(gè)游戲英雄的一句臺(tái)詞“時(shí)間不在于你擁有多少筛峭,而在于你怎樣使用”铐刘。今天我們就來(lái)介紹一下時(shí)間的使用方式定時(shí)器,死板的定理向來(lái)不是我的風(fēng)格今天我們就通過(guò)一個(gè)例子為開(kāi)頭來(lái)說(shuō)明一下定時(shí)的使用影晓,但絕不僅僅于此镰吵。


驗(yàn)證碼.png

上面兩張圖展示的就是一個(gè)注冊(cè)賬號(hào)時(shí)發(fā)生手機(jī)短信驗(yàn)證碼的界面,而獲取驗(yàn)證碼的倒計(jì)時(shí)就是用的定時(shí)器來(lái)實(shí)現(xiàn)的挂签。

定時(shí)器簡(jiǎn)單實(shí)現(xiàn)驗(yàn)證碼倒計(jì)時(shí)

為了能夠很好的演示疤祭,我們新建一個(gè)工程用來(lái)顯示我們的倒計(jì)時(shí)功能。如下圖所示饵婆,我們先創(chuàng)建兩個(gè)按鈕勺馆,分別用來(lái)出發(fā)倒計(jì)時(shí)的事件。

倒計(jì)時(shí)按鈕創(chuàng)建
  • 屬性的設(shè)置
@interface ViewController ()
{
    NSInteger _count;
}
@property(nonatomic,strong)UIButton *PushBtn;

@property(nonatomic,strong)UIButton *NSTimerbtn;

@property(nonatomic,strong)UIButton *GCDbtn;

/** 定時(shí)器(這里不用帶*侨核,因?yàn)閐ispatch_source_t就是個(gè)類(lèi)草穆,內(nèi)部已經(jīng)包含了*) */
@property (nonatomic, strong) dispatch_source_t timer;

  • NSTimer 按鈕點(diǎn)擊事件中
self.NSTimerbtn.enabled =NO; //禁止點(diǎn)擊
 _count = 60;
[self.NSTimerbtn setTitle:@"60秒" forState:UIControlStateDisabled];
 [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES];
  • 定時(shí)器事件
-(void)timerFired:(NSTimer *)timer
{
    
    if (_count !=1) {
        _count -=1;
        [self.NSTimerbtn setTitle:[NSString stringWithFormat:@"%ld秒",_count] forState:UIControlStateDisabled];
        
    }
    else
    {
        [timer invalidate];  //定時(shí)器停止
        self.NSTimerbtn.enabled = YES;
        [self.NSTimerbtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [self.NSTimerbtn setTitle:@"獲取驗(yàn)證碼" forState:UIControlStateNormal];
    }
}

這樣基本上就實(shí)現(xiàn)了簡(jiǎn)單的倒計(jì)時(shí),運(yùn)用的方法是NSTimer定時(shí)器搓译。從上面的圖中可以看到悲柱,還有一個(gè)GCD定時(shí)器的用法。

  • GCD定時(shí)器實(shí)現(xiàn)倒計(jì)時(shí)
 __block int count = 10;
    
    // 獲得隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 創(chuàng)建一個(gè)定時(shí)器
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    // 設(shè)置定時(shí)器的各種屬性(幾時(shí)開(kāi)始任務(wù)些己,每隔多長(zhǎng)時(shí)間執(zhí)行一次)
    // GCD的時(shí)間參數(shù)豌鸡,一般是納秒(1秒 == 10的9次方納秒)
    // 何時(shí)開(kāi)始執(zhí)行第一個(gè)任務(wù)
    // dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC) 比當(dāng)前時(shí)間晚3秒
    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
    uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);
    dispatch_source_set_timer(self.timer, start, interval, 0);
    
    // 設(shè)置回調(diào)
    dispatch_source_set_event_handler(self.timer, ^{
        
        count  = count - 1;
        
        [self.GCDbtn setTitle:[NSString stringWithFormat:@"%d秒",count] forState:UIControlStateNormal];
        
        self.GCDbtn.enabled = NO;
        
        [self.GCDbtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

        
        if (count == 0) {
            // 取消定時(shí)器
            dispatch_cancel(self.timer);
            self.timer = nil;
            
            self.GCDbtn.enabled = YES;
            [self.GCDbtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
            [self.GCDbtn setTitle:@"獲取驗(yàn)證碼" forState:UIControlStateNormal];
        }
    });
    
    // 啟動(dòng)定時(shí)器
    dispatch_resume(self.timer);
 

上述兩種方法都可以實(shí)現(xiàn)倒計(jì)時(shí)的功能,如下圖

倒計(jì)時(shí)實(shí)現(xiàn)

真正的開(kāi)始

我們是使用了NSTimer和GCD實(shí)現(xiàn)了倒計(jì)時(shí)段标,但是對(duì)它們的了解到底有多深呢涯冠。面對(duì)GCD和NSTimer我們要選擇哪種方式呢。要想做出選擇首先我們要對(duì)他們有一定的了解然后才能誰(shuí)才是適合我們的逼庞。

如果選擇GCD

如果說(shuō)選擇了GCD定時(shí)器蛇更,像上面那樣寫(xiě)一個(gè)也就可以忍,但是如果用到多個(gè)定時(shí)器的話,每次都要寫(xiě)很多械荷,實(shí)在太累了共耍,就想封裝一個(gè),但是我寫(xiě)好之后吨瞎,看到另一篇簡(jiǎn)書(shū)的內(nèi)容痹兜,人家已經(jīng)封裝了,而且竟然比我封裝的還全面(-_-`)颤诀,這里就不放我自己的了字旭,放個(gè)傳送門(mén)吧(哈哈)GCD定時(shí)器封裝的代碼
具體的用法作者講的比較清楚,這里在說(shuō)一下崖叫,怎么用這個(gè)封裝的定時(shí)器來(lái)實(shí)現(xiàn)倒計(jì)時(shí)驗(yàn)證碼遗淳。首先在按鈕的點(diǎn)擊事件里,加入倒計(jì)時(shí)心傀,然后實(shí)現(xiàn)倒計(jì)時(shí)里的方法屈暗。

    [[JX_GCDTimerManager sharedInstance]cancelTimerWithName:@"mytimers"];
    
        __weak typeof(self) weakSelf = self;
    
    [[JX_GCDTimerManager sharedInstance]scheduledDispatchTimerWithName:@"mytimers" timeInterval:1 queue:nil
repeats:YES actionOption:AbandonPreviousAction action:^{
    
    [weakSelf dosomthing];
    

下一步實(shí)現(xiàn) [weakSelf dosomthing]方法,從而完成點(diǎn)擊按鈕顯示數(shù)字脂男。這里需要注意的就是UI的刷新必須回到主線程养叛,因?yàn)橛?jì)數(shù)是在子線程里可以完成的,但是UI的刷新如果不回到主線程是不會(huì)刷新的宰翅,你會(huì)誤以為定時(shí)器無(wú)效弃甥,然而并不是。

-(void)dosomthing{
    
    __weak typeof(self) weakSelf = self;

    _count  = _count - 1;
    
    NSLog(@"%ld",_count);
    
         dispatch_sync(dispatch_get_main_queue(), ^{
            weakSelf.GCDbtn.enabled = NO;
            
            [weakSelf.GCDbtn setTitle:[NSString stringWithFormat:@"%ld秒",_count] forState:UIControlStateNormal];
            
            
            [weakSelf.GCDbtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        });  
    
    if (_count< 1) {
        [[JX_GCDTimerManager sharedInstance] cancelTimerWithName:@"mytimers"];
        
        weakSelf.GCDbtn.enabled = YES;
                    [weakSelf.GCDbtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
                    [weakSelf.GCDbtn setTitle:@"獲取驗(yàn)證碼" forState:UIControlStateNormal];
        _count = 10;
    }
}

這樣我們就實(shí)現(xiàn)了用封裝的GCD定時(shí)器實(shí)現(xiàn)的倒計(jì)時(shí)方法汁讼。自己把GCD定時(shí)器封裝起來(lái)還是有很多好處的淆攻,用GCD定時(shí)器相對(duì)于NSTimer可以幫我們減少內(nèi)存泄漏的風(fēng)險(xiǎn),同時(shí)GCD還可以幫我們處理線程級(jí)的邏輯嘿架。有了封裝的定時(shí)器我們就可以隨心所欲的使用了啊瓶珊。

如果選擇NSTimer

NSTimer用起來(lái)也只是簡(jiǎn)單的使用,對(duì)他的認(rèn)識(shí)也確實(shí)不夠深入耸彪,這里就推薦一篇個(gè)人認(rèn)為比較好的文章吧伞芹,反正我看了之后是學(xué)習(xí)良多,感慨iOS要學(xué)習(xí)的地方還很多啊搜囱。奉上博客原文:NSTimer你真的會(huì)用了嗎

  • NSTimer不是一種實(shí)時(shí)的機(jī)制丑瞧,會(huì)存在延遲柑土,而且延遲的程度跟當(dāng)前線程的執(zhí)行情況有關(guān)蜀肘。會(huì)因?yàn)楫?dāng)前線程的堵塞導(dǎo)致延時(shí)。
  • 必須得把timer添加到runloop中稽屏,它才會(huì)生效扮宠。
  • 要讓timer生效,必須保證該線程的runloop已啟動(dòng),而且其運(yùn)行的runloopmode也要匹配坛增。

后記

關(guān)于定時(shí)器的這里就先說(shuō)到這么多获雕,有自己使用的也有自己學(xué)到的,感覺(jué)要學(xué)習(xí)的還很多收捣,有許多博客和文章確實(shí)能學(xué)到許多東西届案,比如,文中舉例的兩篇文章罢艾,都講解的比較深入楣颠,器這里權(quán)且當(dāng)做是拋磚引玉吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咐蚯,一起剝皮案震驚了整個(gè)濱河市童漩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌春锋,老刑警劉巖矫膨,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異期奔,居然都是意外死亡侧馅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)能庆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)施禾,“玉大人,你說(shuō)我怎么就攤上這事搁胆∶指悖” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵渠旁,是天一觀的道長(zhǎng)攀例。 經(jīng)常有香客問(wèn)我,道長(zhǎng)顾腊,這世上最難降的妖魔是什么粤铭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮杂靶,結(jié)果婚禮上梆惯,老公的妹妹穿的比我還像新娘。我一直安慰自己吗垮,他們只是感情好垛吗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著烁登,像睡著了一般怯屉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天锨络,我揣著相機(jī)與錄音赌躺,去河邊找鬼。 笑死羡儿,一個(gè)胖子當(dāng)著我的面吹牛礼患,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掠归,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼讶泰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了拂到?” 一聲冷哼從身側(cè)響起痪署,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兄旬,沒(méi)想到半個(gè)月后狼犯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡领铐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年悯森,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绪撵。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瓢姻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出音诈,到底是詐尸還是另有隱情幻碱,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布细溅,位于F島的核電站褥傍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏喇聊。R本人自食惡果不足惜恍风,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望誓篱。 院中可真熱鬧朋贬,春花似錦、人聲如沸窜骄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)啊研。三九已至御滩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間党远,已是汗流浹背削解。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沟娱,地道東北人氛驮。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像济似,于是被迫代替她去往敵國(guó)和親矫废。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)砰蠢、插件蓖扑、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評(píng)論 4 62
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,129評(píng)論 25 707
  • 聽(tīng)著John這學(xué)期推薦的歌復(fù)習(xí)英國(guó)文學(xué), 1.聽(tīng)到Lullaby my sweet baby有點(diǎn)感人:This s...
    去社閱讀 799評(píng)論 0 2
  • 跑步五年了 出國(guó)比賽卻是第一次 選擇了名氣最大的UTMB (ultra trail du mont blanc)越...
    夢(mèng)是假的897閱讀 659評(píng)論 0 1
  • 終于又一次不是肚子疼得睡不踏實(shí)了,是肚子疼得竞惋,清醒得如同一盆涼水柜去,醍醐灌頂;如同冬日走在風(fēng)中拆宛,哈出一股熱氣嗓奢;如同陽(yáng)...
    愛(ài)吃貓的黃桃蝦閱讀 767評(píng)論 0 0