開篇:要想理解Block和委託,最快的方法是搞明白「回調函數」這個概念。html
作爲初級選手,咱們把Block、委託、回調函數,視爲同一原理的三種不一樣名稱。也就是說,如今,咱們把這三個名詞當成一回事。在這篇文章內,Block就是回調函數,委託也是回調函數,再也不做詳細的區分了。OK,Action!編程
那麼,什麼是回調函數?「回調」概念的主語是誰?網絡
舉個栗子(僞代碼):多線程
首先有個類,咱們姑且稱之爲A類吧。async
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 拿着工資各類敗家…… } } ]; }
關於回調函數,大白話總結!不必定全,可是絕對易懂。spa
第1個問題:什麼是回調函數?.net
回調函數,本質上也是個函數(擱置函數和方法的爭議,就當這兩者是一回事)。由「聲明」、「實現」、「調用」三部分組成。線程
在上面的例子中,我能夠看出,函數amount(實際上是Block),的聲明和調用在A類中,而實現部分在B類中。也就是說,B類實現了amount函數,但並無權限調用,最終仍是 由A類觸發調用。咱們稱這樣的機制爲「回調」。意思是「雖然函數的實現寫在B類中,可是真正的調用仍是得由A類來完成。」正常函數「函數聲明、實現均在一個類中完成。」code
一句大白話理解「回調」的概念:「函數的實現部分雖然不在老家(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中使用的變量,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操做 }); }); }