詳解iOS中多倒計時場景的解決方案
背景
在我們開發(fā)APP的過程中,或多或少都遇到過需要使用倒計時的場景,大多數(shù)應(yīng)用中的用戶登錄注冊過程中獲取驗證碼的倒計時,電商或者外賣APP中的訂單送達的倒計時,以及秒殺類APP的秒殺倒計時等。對于這些需要倒計時的場景,通常情況下的解決方案是:在需要展示倒計時的各View模塊各自維護一個自己的倒計時Timer,通過Timer的回調(diào)和模塊本身需要的倒計時時間來更新對應(yīng)View的倒計時的顯示,再在此基礎(chǔ)上加上對應(yīng)的時間校準方案,一個簡單的倒計時需求就完成了。
問題
對于APP內(nèi)倒計時的業(yè)務(wù)如果只出現(xiàn)在單一的頁面或者是少數(shù)的頁面場景中沒什么太大的問題的,通常對于秒殺類APP的倒計時場景往往是在某個頁面或者某幾個頁面中有多個倒計時共同存在的,這種產(chǎn)品需求的技術(shù)展現(xiàn)方式可能是TableView或者CollectionView中的多個Cell,也可能是多個自定義的View模塊,如果我們此時依然使用每個Cell或者每個View模塊各自維護一個單獨的倒計時Timer,當前APP內(nèi)就會同時存在多個定時器Timer,這對于性能來說是存在一定程度的影響的。那么我們怎么才能更好的解決多倒計時場景的問題呢?
解決方案
既然我們不能讓每一個顯示倒計時的View模塊各自維護一個定時器Timer,那我們就提供一個專門的模塊TimerService來提供倒計時的服務(wù),TimerService內(nèi)部負責維護唯一一個定時器,同時提供添加和移除監(jiān)聽者的接口以及監(jiān)聽者需要實現(xiàn)的協(xié)議protocol,內(nèi)部通過HashTable來存儲監(jiān)聽者,每次定時器回調(diào),遍歷所有監(jiān)聽者進行回調(diào),監(jiān)聽者在不需要接收定時器回調(diào)的時候只需要從TimerService中移除即可。
TimerService.h對外提供的API和監(jiān)聽者需要實現(xiàn)的協(xié)議主要如下:
//監(jiān)聽者需要實現(xiàn)的協(xié)議 @protocol TimerListener <NSObject> @required - (void)didOnTimer:(TimerService *)timer; @end //對接提供的主要接口 + (instancetype)sharedInstance; - (void)addListener:(id<TimerListener>)listener; - (void)removeListener:(id<TimerListener>)listener;
TimerService.m的內(nèi)部主要實現(xiàn)如下:
//定時器回調(diào) - (void)onTimer { [self.map.allObjects enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { id<TimerListener> listener = obj; if([listener respondsToSelector:@selector(didOnTimer:)]){ [listener didOnTimer:self]; } }]; } #pragma mark - public - (void)addListener:(id<TimerListener>)listener { TIMER_SERVICE_LOCK(self.operationsLock) if(![self.map containsObject:listener]){ [self.map addObject:listener]; if(self.map.count > 0){ //啟動 [self startTimer]; } } TIMER_SERVICE_UNLOCK(self.operationsLock) } - (void)removeListener:(id<TimerListener>)listener { TIMER_SERVICE_LOCK(self.operationsLock) if([self.map containsObject:listener]){ [self.map removeObject:listener]; if(self.map.count == 0){ //暫停 [self stopTimer]; } } TIMER_SERVICE_UNLOCK(self.operationsLock) }
使用
需要接收定時器回調(diào)的模塊,只要實現(xiàn)TimerListener協(xié)議,在需要接收定時器回調(diào)的時把其添加到TimerService中,在業(yè)務(wù)不需要接收定時器回調(diào)的時候把其從TimerService中移除即可,這樣所有的倒計時業(yè)務(wù)只需要維護一個定時器即可搞定。
其他
當然要很好的搞定一個倒計時還需要解決其他一些問題,比如客戶端時間校準問題,關(guān)于這個問題推薦細細讀一下MrPeak君的一篇文章《iOS關(guān)于時間的處理》。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS 16 CocoaAsyncSocket 崩潰修復詳解
這篇文章主要為大家介紹了iOS 16 CocoaAsyncSocket 崩潰修復詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01淺述iOS11 Xcode 9 按住command 單擊 恢復到從前(直接跳轉(zhuǎn)到定義)
這篇文章主要介紹了 iOS11 Xcode 9 按住command 單擊 恢復到從前(直接跳轉(zhuǎn)到定義)的相關(guān)資料,需要的朋友可以參考下2017-10-10詳解使用Xcode進行iOS設(shè)備無線調(diào)試
這篇文章主要介紹了詳解使用Xcode進行iOS設(shè)備無線調(diào)試,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12iOS 條碼及二維碼掃描(從相冊中讀取條形碼/二維碼)及掃碼過程中遇到的坑
本文主要給大家介紹ios中從手機相冊中讀取條形碼和二維碼的問題及解決辦法,需要的朋友參考下2017-01-01iOS CAReplicatorLayer實現(xiàn)脈沖動畫效果
這篇文章主要介紹了iOS CAReplicatorLayer實現(xiàn)脈沖動畫效果 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06