iOS開發——多線程完成短信獲取按鈕倒計時

sdzxx2008 7年前發布 | 10K 次閱讀 iOS開發 多線程 移動開發

現在的APP應用中,用手機獲取短信驗證碼是非常常見的一個功能,而往往要求的效果就是在按下獲取驗證碼之后,驗證碼的按鈕開始倒計時,例如30秒后重新獲取。而我們如何來完成這個效果呢,其實很簡單,用一個定時器來計時,設置定時器的時間為UIButton的Title,而這個步驟我們一般用多線程的定時器dispatch source來定時產生事件。

在網上看了別人寫的代碼,復用性比較差,沒有對這個方法進行良好的封裝,我在這里貼一段修改后的代碼,基本上大家黏貼過去就能復用。而后面我會解釋這個代碼的多線程方面的一些問題。

#pragma mark - 倒計時獲取驗證碼
-(void)changeTimeOut:(int)timeOut btnTag:(int)btnTag{
    __block int timeout=timeOut;
    dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer=dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), 1.0*NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{
        if (timeout<=0) {
            dispatch_source_cancel(_timer);
            //dispatch_release(_timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                //倒計時結束
                _smsCodeBtn=(UIButton*)[self.view viewWithTag:[[NSString stringWithFormat:@"%d",btnTag] intValue]];
                [_smsCodeBtn setTitle:@"重新獲取驗證碼" forState:UIControlStateNormal];
                [_smsCodeBtn setUserInteractionEnabled:YES];
                [_smsCodeBtn setTitleColor:[UIColor colorWithRed:53.0f/255.0f   green:53.0f/255.0f blue:68.0f/255.0f alpha:1] forState:UIControlStateNormal];
                [_smsCodeBtn.layer setBorderColor:[UIColor colorWithRed:53.0f/255.0f green:53.0f/255.0f blue:68.0f/255.0f alpha:1].CGColor];
            });
        }else{
            NSString* strTime=[NSString stringWithFormat:@"%d秒后重新獲取",(int)(timeout)];
            dispatch_async(dispatch_get_main_queue(), ^{
                //倒計時
                _smsCodeBtn=(UIButton*)[self.view viewWithTag:[[NSString stringWithFormat:@"%d",(int)btnTag] intValue]];
                [_smsCodeBtn setTitle:strTime forState:UIControlStateNormal];
                [_smsCodeBtn setTitleColor:[UIColor colorWithRed:153.0f/255.0f green:153.0f/255.0f blue:153.0f/255.0f alpha:1] forState:UIControlStateNormal];
                [_smsCodeBtn.layer setBorderColor:[UIColor colorWithRed:153.0f/255.0f green:153.0f/255.0f blue:153.0f/255.0f alpha:1].CGColor];
                [_smsCodeBtn setUserInteractionEnabled:NO];
            });
            timeout--;
        }
    });
    dispatch_resume(_timer);
}

這段代碼中smsCodeBtn就是我定義的獲取短信驗證碼的UIButton,你們復制下去只要把frame屬性和ui屬性改一改,就完全可以直接用了。

那么接下來我們來講講這段代碼中多線程的問題。

首先我們先用 dispatch_get_global_queue 來開啟一個全局隊列,之后用 dispatch_source_t 來產生定時事件。所有定時器 dispatch_source 都是間隔定時器,一旦創建,會按你指定的間隔定期遞送事件。你需要為定時器 dispatch_source 指定一個期望的定時器事件精度,也就是leeway值,讓系統能夠靈活地管理電源并喚醒內核。例如系統可以使用leeway值來提前或延遲觸發定時器,使其更好地與其他系統事件結合。創建自己的定時器時,你應該盡量指定一個leeway值。

就算你指定的leeway值為0,也不要期望定時器能夠按照精確地納秒來觸發事件,系統會盡可能地滿足你的需求,但是無法保證完全精確的觸發時間。

如果你使用 dispatch_walltime 函數來設置定時器 dispatch_source ,則定時器會根據掛鐘時間來跟蹤,這種定時器比較適合觸發間隔相對比較大的場合,可以防止定時器觸發時間出現太大誤差。

dispatch_time 類型的時間我們可以通過 dispatch_time 來創建,也可以通過 dispatch_walltime 來創建。前者創建的時間多以第一個參數為參照物,之后過多久執行任務。后者多用于創建絕對時間,如某年某月某日某時某分執行某任務,比如鬧鐘的設置。

最后我們用 dispatch_source_set_event_handler 這個方法來創建我們要完成的任務,很簡單的語句,一個block閉包,里面的內容當然是自由發揮的咯。

所以交代清楚GCD中時間事件,這段代碼就非常容易理解了。

代碼很短也就不傳到Github上的demo了。如果有寫的不對的地方,歡迎交流。

 

來自:http://www.jianshu.com/p/bb42e5fc9886

 

 本文由用戶 sdzxx2008 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!