詳解iOS 用于解決循環(huán)引用的block timer
一、什么是回調(diào)函數(shù)?
回調(diào)函數(shù),本質(zhì)上也是個函數(shù)(擱置函數(shù)和方法的爭議,就當(dāng)這二者是一回事)。由“聲明”、“實現(xiàn)”、“調(diào)用”三部分組成。
在上面的例子中,我可以看出,函數(shù)amount(其實是Block),的聲明和調(diào)用在A類中,而實現(xiàn)部分在B類中。也就是說,B類實現(xiàn)了amount函數(shù),但并沒有權(quán)限調(diào)用,最終還是 由A類觸發(fā)調(diào)用。我們稱這樣的機(jī)制為“回調(diào)”。意思是“雖然函數(shù)的實現(xiàn)寫在B類中,但是真正的調(diào)用還是得由A類來完成?!闭:瘮?shù)“函數(shù)聲明、實現(xiàn)均在一個類中完成?!?/p>
一句大白話理解“回調(diào)”的概念:“函數(shù)的實現(xiàn)部分雖然不在老家(A類),但是最終的調(diào)用還是由老家人完成”,這樣的函數(shù)就叫做回調(diào)函數(shù)?!袄霞胰苏{(diào)用你,就叫回調(diào),因為你本來就屬于老家。
用《無間道》理解“回調(diào)函數(shù)”概念:
香港警務(wù)處(類):
招聘了一名警察張三(聲明函數(shù)),并培養(yǎng)、訓(xùn)練他(實現(xiàn)函數(shù))。
招聘了一名警察陳仁貴(聲明函數(shù)),但并沒有培養(yǎng)他,而是被送進(jìn)了三合會。但有任務(wù)的時候,警務(wù)處會調(diào)用陳仁貴(回調(diào)函數(shù))。
廉政總署(類):使用警務(wù)處的張三(普通調(diào)用)。
三合會(類):培養(yǎng)、訓(xùn)練陳仁貴(實現(xiàn)函數(shù))。
第二個問題:什么情況下使用回調(diào)函數(shù)?
假設(shè)有A、B兩個類。
(1)A類有多種形態(tài),要在B類中實現(xiàn)回調(diào)函數(shù)。如假設(shè)A類是網(wǎng)絡(luò)請求開源類ASIHttpRequest,它可能請求成功,也可能請求失敗。這個時候,B類就要針對以上兩個情況,作不同的處理。
(2)A類的形態(tài)由B類決定時,要在B類中實現(xiàn)回調(diào)函數(shù)。如UITableView類就會提供很多回調(diào)函數(shù)(iOS專業(yè)術(shù)語稱“委托”方法)
(3)A類需要向B類傳遞數(shù)據(jù)時,可以在B類中實現(xiàn)回調(diào)函數(shù)(A類一般是數(shù)據(jù)層比較耗時的操作類)。如舉的那個發(fā)工資的例子。在實際編程中,這樣的機(jī)制有個好處就是可以提升用戶的操作體驗。比如用戶從X頁面跳轉(zhuǎn)到Y(jié)頁面,需要向網(wǎng)絡(luò)請求數(shù)據(jù),而且比較耗時,那我們怎么辦?有三種方案:第一種就是在X頁面展示一個旋轉(zhuǎn)指示器,當(dāng)收到網(wǎng)絡(luò)傳回的數(shù)據(jù)時,在展現(xiàn)Y頁面。第二種就是使用回調(diào)函數(shù)。用戶從X頁面直接跳轉(zhuǎn)到Y(jié)頁面,Y頁面需要到數(shù)據(jù)讓數(shù)據(jù)層去執(zhí)行,當(dāng)收到數(shù)據(jù)時,再在Y頁面展現(xiàn)。第三種就是在Y頁面中開啟多線程。讓一個子線程專門到后臺去取數(shù)據(jù)。綜合來說,第二種更加簡介易懂,而且代碼緊湊。
第三個問題:使用回調(diào)函數(shù)有什么好處?
(1)可以讓實現(xiàn)方,根據(jù)回調(diào)方的多種形態(tài)進(jìn)行不同的處理和操作。(ASIHttpRequest)
(2)可以讓實現(xiàn)方,根據(jù)自己的需要定制回調(diào)方的不同形態(tài)。(UITableView)
(3)可以將耗時的操作隱藏在回調(diào)方,不影響實現(xiàn)方其它信息的展示。
(4)讓代碼的邏輯更加集中,更加易讀。
什么是回調(diào)函數(shù)?——就是由聲明函數(shù)的類來調(diào)用的函數(shù)叫做回調(diào)函數(shù)。普通函數(shù)可以讓任何類調(diào)用。
“回調(diào)”的主語是誰?——聲明“回調(diào)函數(shù)”的那個類。
Block、委托、通知、回調(diào)函數(shù),它們雖然名字不一樣,但是原理都一樣,都是“回調(diào)機(jī)制”的思想的具體實現(xiàn)!
iOS 10的時候NSTimer新增了一個帶block的API:
蘋果的官方文檔里說,將這個timer本身作為參數(shù)傳給block以此來避免循環(huán)引用:
/// - parameter: block The execution body of the timer; the timer itself is passed as the parameter to this block when executed to aid in avoiding cyclical references
有了這個API再也不需要繁瑣的手動注銷timer,結(jié)合weakSelf就可以輕松處理循環(huán)引用,如:
__weak typeof(self) weakSelf = self; self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { __strong typeof(self) strongSelf = weakSelf; [strongSelf printNum]; }];
在這個API出現(xiàn)之前,self和timer的引用關(guān)系是:self->timer->self
現(xiàn)在的引用關(guān)系是:self->timer->weakSelf
但是只有iOS 10及之后的系統(tǒng)才能使用此API,而我們一般都是適配到iOS 8,所以有必要擴(kuò)展一下。
如何擴(kuò)展?
簡單點(diǎn),寫個category,直接復(fù)制蘋果的API進(jìn)去(思考API設(shè)計的時間都省了😎),然后加上前綴:
+ (NSTimer *)cq_scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block { return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(cq_callBlock:) userInfo:[block copy] repeats:repeats]; } + (void)cq_callBlock:(NSTimer *)timer { void (^block)(NSTimer *timer) = timer.userInfo; !block ?: block(timer); }
你不是把timer作為參數(shù)傳給block嗎?那我也這樣搞。
然后就可以像使用系統(tǒng)API那樣使用了:
__weak typeof(self) weakSelf = self; self.timer = [NSTimer cq_scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer *timer) { __strong typeof(self) strongSelf = weakSelf; [strongSelf printNum]; }];
最后提供一個此timer使用的具體demo:https://github.com/CaiWanFeng/CQCountDownButton
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS復(fù)數(shù)cell下優(yōu)雅的代碼結(jié)構(gòu)詳解
這篇文章主要給大家介紹了關(guān)于iOS復(fù)數(shù)cell下優(yōu)雅的代碼結(jié)構(gòu)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用iOS具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04IOS程序開發(fā)之跳轉(zhuǎn)短信發(fā)送界面實現(xiàn)發(fā)送短信功能
在程序開發(fā)中,我們經(jīng)常遇到這樣一功能:某個程序里面發(fā)送一些短信驗證,那么基于代碼是如何實現(xiàn)的呢?下面小編通過本文給大家介紹IOS程序開發(fā)之跳轉(zhuǎn)短信發(fā)送界面實現(xiàn)發(fā)送短信功能,有需要的朋友拿去用2016-01-01iOS應(yīng)用開發(fā)中導(dǎo)航欄按鈕UIBarButtonItem的添加教程
這篇文章主要介紹了iOS應(yīng)用開發(fā)中導(dǎo)航欄按鈕UIBarButtonItem的添加教程,文中詳細(xì)介紹了使用UINavigationController導(dǎo)航控制器添加的過程,需要的朋友可以參考下2016-02-02HTTP/2 協(xié)議用于 iOS 推送提醒服務(wù) (APNS)
基于JSON的請求和響應(yīng)對于每個通知,如果成功響應(yīng),將會返回200標(biāo)識 - 不用再去猜測通知是否被接收到響應(yīng)錯誤將會以JSON字符消息的長度從2048個字節(jié)增加到4096個字節(jié)連接狀態(tài)可以通過HTTP/2的ping框架來進(jìn)行檢查.2016-04-04iOS開發(fā)中實現(xiàn)郵件和短信發(fā)送的簡單示例
這篇文章主要介紹了iOS開發(fā)中實現(xiàn)郵件和短信發(fā)送的簡單示例,編程語言依然是傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-09-09IOS實現(xiàn)左右兩個TableView聯(lián)動效果
在我們?nèi)粘i_發(fā)IOS中,經(jīng)常見到兩個tableview的聯(lián)動,滑動一側(cè)tableview,另一側(cè)tableview跟著滑動,其實實現(xiàn)起來比較簡單,只是需要搞清楚他們之間的區(qū)別和聯(lián)系,下面一起來看看如何實現(xiàn)。2016-08-08iOS開發(fā)中文件的上傳和下載功能的基本實現(xiàn)
這篇文章主要介紹了iOS開發(fā)中文件的上傳和下載功能的基本實現(xiàn),并且下載方面講到了大文件的多線程斷點(diǎn)下載,需要的朋友可以參考下2015-11-11怎么防止ios系統(tǒng)被抓包?防止ios系統(tǒng)被抓包的方法
怎么防止ios系統(tǒng)被抓包?下面小編就為大家分享一篇防止ios系統(tǒng)被抓包的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12