細(xì)數(shù)Objective-C中的回調(diào)機(jī)制

之前看的別人的保存的
一、協(xié)議

協(xié)議主要是提供接口、或是類似C++多重繼承功能,為類提供一種修飾機(jī)制。協(xié)議不是為回調(diào)而生的,它應(yīng)該表述一組互操作約定。

優(yōu)點(diǎn):

實(shí)現(xiàn)簡單,容易理解。
強(qiáng)類型檢查。
缺點(diǎn):

類與類間建立了比較強(qiáng)的耦合關(guān)系
有可能需要較長期保存委托以進(jìn)行回調(diào)。如果保留的委托需要有獨(dú)占性,可能會(huì)給單件模式、以及多線程帶來麻煩。
類只能通過一個(gè)方法完成一種類型的回調(diào)。代碼邏輯很容易集中到一個(gè)方法中。
大部分回調(diào)使用實(shí)際無需通過協(xié)議暴露給外部。

二、使用respondsToSelector和performSelector進(jìn)行回調(diào)。

利用OBJC的運(yùn)行時(shí)特性,查找對象的消息進(jìn)行回調(diào)

優(yōu)點(diǎn):

與OBJC代碼兼容性好。
具有延遲執(zhí)行等特性。
輕量級(jí)的回調(diào)機(jī)制。
缺點(diǎn):

回調(diào)產(chǎn)生的返回值只能為id類型,int等類型會(huì)產(chǎn)生錯(cuò)誤。
參數(shù)最多只能傳入兩個(gè)。但可以通過建立包含多個(gè)參數(shù)的參數(shù)類進(jìn)行回避。同時(shí)返回值限制也可通過此方式解決,即建立一個(gè)輸入類和一個(gè)輸出類。NSInvocation也提供了多參數(shù)的解決方法。

如果以

[target performSelector: @selector(callback)];

方式建立回調(diào),則需要對類的回調(diào)消息名建立約定,且回調(diào)消息名具有獨(dú)占性,即一個(gè)類中只能以此消息名進(jìn)行回調(diào)。

如果通過外部傳入SEL建立回調(diào)

[target performSelector: sel];

或是外部傳入字符串建立回調(diào)

[target performSelector:NSSelectorFromString(@"callback")];

使用自動(dòng)引數(shù)編譯器特征(ARC)會(huì)產(chǎn)生警告“performSelector may cause a leak because its selector is unknown”

使用此種方式建立回調(diào),當(dāng)傳入一個(gè)不符合約定的消息時(shí),會(huì)產(chǎn)生副作用繼續(xù)運(yùn)行,而非報(bào)錯(cuò)。比如約定消息有2個(gè)參數(shù),但傳入消息只有1個(gè)參數(shù),則按照參數(shù)約定順序屏蔽掉最后傳入的參數(shù)?;蚴莻魅胂⒕哂?個(gè)參數(shù),則多余的參數(shù)值未初始化。

三、函數(shù)指針

傳統(tǒng)的C語言回調(diào)機(jī)制。

優(yōu)點(diǎn):

輕量級(jí)的回調(diào)機(jī)制。
只約定返回值和參數(shù),而非函數(shù)名。無參數(shù)、返回值限制,使用靈活。
編譯器提供類型檢查。(錯(cuò)誤時(shí)產(chǎn)生警告)
缺點(diǎn):

與OBJC的消息機(jī)制不兼容。因?yàn)橄⒉⒎荂語言中那樣,函數(shù)名對應(yīng)函數(shù)指針。即只能對C函數(shù)進(jìn)行回調(diào)。
傳入不符合約定的函數(shù)指針時(shí),產(chǎn)生副作用繼續(xù)運(yùn)行,而非報(bào)錯(cuò)。

四、objc_msgSend

通過導(dǎo)入#import <objc/message.h>獲得運(yùn)行時(shí)的消息調(diào)用。

其定義為

id objc_msgSend(id theReceiver, SEL theSelector, ...)

優(yōu)點(diǎn):

輕量級(jí)的回調(diào)機(jī)制。
無傳入?yún)?shù)限制。
相比performSelector,使用自動(dòng)引數(shù)特征時(shí),不產(chǎn)生警告。
同系列的方法支持double、struct等類型的返回值,但仍然不支持int型返回值(可使用NSNumber包裝以回避)。
缺點(diǎn):

傳入不符合約定的消息時(shí),產(chǎn)生副作用繼續(xù)運(yùn)行,而非報(bào)錯(cuò)。

五、IMP

IMP類似于OBJC提供的函數(shù)指針,它通過methodForSelector方法查詢傳入的Selector,以獲得函數(shù)的入口地址。

其定義為

id (*IMP)(id, SEL, ...)

相比普通C語言的函數(shù)指針,其定義多了id,SEL這兩個(gè)強(qiáng)制參數(shù)約定,其他與函數(shù)指針無異。

優(yōu)點(diǎn):

輕量級(jí)的回調(diào)機(jī)制。
傳入不符合約定的消息時(shí),報(bào)錯(cuò)。
無傳入?yún)?shù)限制。返回值可通過強(qiáng)轉(zhuǎn)獲得,無類型限制。如:
typedef int (*CBFUNC)(id, SEL, int, int, int); // 定義函數(shù)指針類型

  int ret = ((CBFUNC)callback)(self, sel, param1, param2, param3); // 強(qiáng)制轉(zhuǎn)換

這里的id和SEL只是OBJC系統(tǒng)約定的占位,自定義回調(diào)時(shí)無實(shí)際意義。

由于此階段實(shí)際是函數(shù)指針調(diào)用,因此最好還是typedef定義函數(shù)指針,然后對IMP強(qiáng)轉(zhuǎn)一下,以免出現(xiàn)錯(cuò)誤,也能提供一些編譯期保護(hù)。

缺點(diǎn):

依然不能提供如同協(xié)議和函數(shù)指針的編譯期類型檢查

六、NSNotificationCenter

NSNotificationCenter是OBJC提供的消息機(jī)制。它有些類似于觀察者模式,通過關(guān)注感興趣的消息,建立回調(diào)。NSNotificationCenter提供了一種低耦合的對象通訊機(jī)制,特別適合無指定對象的一對多回調(diào)。

主要方法:

1)獲取消息中心實(shí)例(系統(tǒng)已創(chuàng)建,單件模式)

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

2)發(fā)送消息。(事件發(fā)生時(shí)調(diào)用)

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

[nc postNotificationName: NOTIFY_MSG_UC_COMMON_PLAYER_PLAY   // 消息名(字符串)

                  object:self                                // 消息源

                userInfo:nil];                               // 用戶字典(傳遞更多自定義參數(shù))

3)注冊消息

[nc addObserver: self                              // 觀察者

       selector: @selector(handleNotify_Play:)     // 回調(diào)

           name: NOTIFY_MSG_UC_COMMON_PLAYER_PLAY  // 監(jiān)聽消息

         object: nil];                             // 消息源

4)注銷消息

[nc removeObserver: self];

5)回調(diào)定義

- (void) handleNotify_Play:(NSNotification *)note;

只有一個(gè)參數(shù)

 NSNotification*

 –name      // 消息名

 –object    // 消息源

 –userInfo  // 用戶字典

優(yōu)點(diǎn):

回調(diào)對象間耦合度低。相互之間可不必知道對方存在。
通過消息傳遞的信息無限制。
觀察者可選擇特定消息、特定對象,或者特定對象的特定消息進(jìn)行觀察。
缺點(diǎn):

缺乏時(shí)序性。當(dāng)事件發(fā)生時(shí),回調(diào)執(zhí)行的先后次序不確定。也不能等待回調(diào)完成執(zhí)行后續(xù)操作。解決:1)使用傳統(tǒng)回調(diào)機(jī)制。2)多線程時(shí),可使用NSCondition同步線程。3)使用更多的消息。(過多使用可能導(dǎo)致混亂)

七、Block

Block是OBJC提供的一種運(yùn)行時(shí)方法機(jī)制,類似于Javascript的匿名函數(shù)。它提供了一種運(yùn)行時(shí)的臨時(shí)回調(diào)機(jī)制。

Block對象的聲明:

聲明一個(gè)參數(shù)為int,返回值為int的Block對象cb。

int (^cb)(int);

也可以通過typedef簡化定義。

typedef int(^BLOCK_CALLBACK_FUNC)(int);

BLOCK_CALLBACK_FUNC cb = …

回調(diào)函數(shù)定義:

-(int)handleBlockCallbackFunc: (BLOCK_CALLBACK_FUNC)callback

{

  return callback(10);

}

回調(diào)函數(shù)使用:

1)賦值后使用

 BLOCK_CALLBACK_FUNC cb =

   ^(int param)

   {

     NSLog(@"Block Msg: %d", param);

     return param*2;

   };

   int ret = [self handleBlockCallbackFunc:cb];

2)使用時(shí)賦值

 int ret = [self handleBlockCallbackFunc:

             ^(int param) {

               NSLog(@"Block Msg: %d", param);

               return param*2;

             }];

注意:

1)block對象使用的變量、參數(shù)在運(yùn)行時(shí)被綁定,因此可以直接使用??臻g建立的變量,無需參數(shù)傳入。但block對象的創(chuàng)建依然有生命周期限制,因此傳入異步調(diào)用的block對象時(shí),如果是??臻g創(chuàng)建的block,必須

使用Block_copy()將block拷出備份,然后使用Block_release()將block釋放。參見Using Blocks章,Patterns to Avoid節(jié)

2)對于在??臻g聲明的變量,綁定到block時(shí)被標(biāo)記為const。只能讀取不能寫入。如果需要寫入,需要用__block對變量進(jìn)行標(biāo)記。此時(shí)block使用的是從??截惖蕉阎械膶ο蟆.?dāng)出block時(shí),如果??捎脛t將堆中對象自動(dòng)拷貝回棧。

優(yōu)點(diǎn):

最輕量級(jí)的回調(diào)機(jī)制。
編譯器類型檢查。
如函數(shù)指針一樣,靈活定義回調(diào)函數(shù)。
缺點(diǎn):

執(zhí)行效率。(影響程度不清楚)
容易導(dǎo)致代碼邏輯集中。
IOS4之后的特性

總結(jié):

OBJC還沒有太完美的輕量級(jí)回調(diào)機(jī)制,只能根據(jù)情況選擇合適的機(jī)制。

單純的回調(diào),且沒有復(fù)用的必要,也無IOS版本限制,可采用block。
單純的回調(diào),有復(fù)用要求,可使用performSelector、objc_msgSend,或是IMP的回調(diào)機(jī)制。
使用自動(dòng)引數(shù)的情況下,盡量不使用performSelector回調(diào)傳入的@Selector,防止警告。
對象間有較多的互操作,對象有復(fù)用的必要,可采用協(xié)議。
無指定對象的一對多回調(diào)采用NSNotificationCenter。
有延遲調(diào)用等特殊應(yīng)用的,可以使用performSelector。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、協(xié)議協(xié)議主要是提供接口、或是類似C++多重繼承功能,為類提供一種修飾機(jī)制。協(xié)議不是為回調(diào)而生的,它應(yīng)該表述一組...
    亦晴工作室閱讀 1,587評論 0 1
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,042評論 0 9
  • geeooooz閱讀 1,695評論 0 1
  • 和小宇分別時(shí),夜色朦朧,天空飄灑著微微的細(xì)雨,我能感到脆脆的顆粒落在藍(lán)綢傘上的聲音。天氣預(yù)報(bào)說:明天會(huì)下...
    儷嘉閱讀 306評論 0 0

友情鏈接更多精彩內(nèi)容