Block、委托、回調函數原理剖析(在Object C語境)——這樣講還不懂,根本不可能!


開篇:要想理解Block和委托,最快的方法是搞明白“回調函數”這個概念。

做為初級選手,我們把Block、委托、回調函數,視為同一原理的三種不同名稱。也就是說,現在,我們把這三個名詞當成一回事。在這篇文章內,Block就是回調函數,委托也是回調函數,不再作詳細的區分了。OK,Action!

那么,什么是回調函數?“回調”概念的主語是誰?

舉個栗子(偽代碼):

首先有個類,我們姑且稱之為A類吧。

A.h 文件

//聲明回調函數:給指定的員工發放工資

-(void)paySalaryForStaff:(int)staffId withMoney:(void(^)(int salary))amount;

//聲明回調函數:告訴所有員工周末加班若干小時

-(void)weekEndWillWorkOverTime:(int)hours

 

A.m 文件

-(void)paySalaryForStaff:(int)staffId withMoney:(void(^)(int salary))amount

 {

   //code 計算指定員工應該發多少工資

   //計算完畢后,觸發回調函數,告訴員工已經給其發了5萬元的工資

    amount(50000);  //具體這5萬元,員工怎么花,就讓員工類來實現

}

B類(員工類)

B.m

-(void)spendMoney

{

   //code 沒有錢,做些無聊的事情,等工資中,如打游戲,看電影……

   //code 又看了50部電影

   //code 設想發了工資怎么花, 創建A類的一個對象a

   [a  paySalaryForStaff:007

       amount:^(int salary)

       {

                        if(salary==50000)

                           {

                             NSLog(@"我靠,這個月績效滿分啊!和朋友慶祝一下!")

                             //code 拿着工資各種敗家……

                           }

       }

   ];

}

關於回調函數,大白話總結!不一定全,但是絕對易懂。

第1個問題:什么是回調函數?

回調函數,本質上也是個函數(擱置函數和方法的爭議,就當這二者是一回事)。由“聲明”、“實現”、“調用”三部分組成。

在上面的例子中,我可以看出,函數amount(其實是Block),的聲明和調用在A類中,而實現部分在B類中。也就是說,B類實現了amount函數,但並沒有權限調用,最終還是 由A類觸發調用。我們稱這樣的機制為“回調”。意思是“雖然函數的實現寫在B類中,但是真正的調用還是得由A類來完成。”正常函數“函數聲明、實現均在一個類中完成。”

一句大白話理解“回調”的概念:“函數的實現部分雖然不在老家(A類),但是最終的調用還是由老家人完成”,這樣的函數就叫做回調函數。“老家人調用你,就叫回調,因為你本來就屬於老家。

用《無間道》理解“回調函數”概念:

香港警務處(類)

招聘了一名警察張三(聲明函數),並培養、訓練他(實現函數)。

招聘了一名警察陳仁貴(聲明函數),但並沒有培養他,而是被送進了三合會。但有任務的時候,警務處會調用陳仁貴(回調函數)。

廉政總署(類):使用警務處的張三(普通調用)。

三合會(類):培養、訓練陳仁貴(實現函數)。

第二個問題:什么情況下使用回調函數?

假設有A、B兩個類。

(1)A類有多種形態,要在B類中實現回調函數。如假設A類是網絡請求開源類ASIHttpRequest,它可能請求成功,也可能請求失敗。這個時候,B類就要針對以上兩個情況,作不同的處理。

(2)A類的形態由B類決定時,要在B類中實現回調函數。如UITableView類就會提供很多回調函數(iOS專業術語稱“委托”方法)

(3)A類需要向B類傳遞數據時,可以在B類中實現回調函數(A類一般是數據層比較耗時的操作類)。如舉的那個發工資的例子。在實際編程中,這樣的機制有個好處就是可以提升用戶的操作體驗。比如用戶從X頁面跳轉到Y頁面,需要向網絡請求數據,而且比較耗時,那我們怎么辦?有三種方案:第一種就是在X頁面展示一個旋轉指示器,當收到網絡傳回的數據時,在展現Y頁面。第二種就是使用回調函數。用戶從X頁面直接跳轉到Y頁面,Y頁面需要到數據讓數據層去執行,當收到數據時,再在Y頁面展現。第三種就是在Y頁面中開啟多線程。讓一個子線程專門到后台去取數據。綜合來說,第二種更加簡介易懂,而且代碼緊湊。

 第三個問題:使用回調函數有什么好處?

(1)可以讓實現方,根據回調方的多種形態進行不同的處理和操作。(ASIHttpRequest

(2)可以讓實現方,根據自己的需要定制回調方的不同形態。(UITableView

(3)可以將耗時的操作隱藏在回調方,不影響實現方其它信息的展示。

(4)讓代碼的邏輯更加集中,更加易讀。

 

什么是回調函數?——就是由聲明函數的類來調用的函數叫做回調函數。普通函數可以讓任何類調用。

“回調”的主語是誰?——聲明“回調函數”的那個類。

 

Block、委托、通知、回調函數,它們雖然名字不一樣,但是原理都一樣,都是“回調機制”的思想的具體實現!

現在明白Block的原理了嗎?

 

參考:

block一點也不神秘————如何利用block進行回調

理解“回調”概念

Blocks Programming Topics

 

Block中的一個重要特性:內存釋放。凡在block中使用的變量,block都將進行自動的釋放。所以,如果使用系統全局變量作為參數傳入block,一定在傳入之前retain一次,才能保證這個變量不被release。如下:

-(void)requestSearchResult
{
    [word retain]; //block中所有變量均將被釋放,字符型除外
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        SQSearchAction *action_search = [[SQSearchAction alloc]initWithDelegate:self];
        
        [action_search requestSearchResultByWord:word type:type pageNo:pageNo flag:flag];
        [action_search release];
        dispatch_async(dispatch_get_main_queue(), ^{
            //更新UI操作
        });
    });
}

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM