深入探究SEL,Method,IMP

SEL

  • SEL方法選擇器,表示一個selector的指針
  • 無論什么類里,只要方法名相同,SEL就相同誉察。項目里的所有SEL都保存在一個NSSet集合里(NSSet集合里的元素不能重復),所以查找對應方法惹谐,只要找到對應的SEL就可以了持偏。
  • SEL實際是根據(jù)方法名hash化了的字符串
SEL sel_registerName(const char *str)//向runtime system注冊一個方法名。如果方法名已經(jīng)注冊氨肌,則放回已經(jīng)注冊的SEL
SEL sel_getUid(const char *str)//同上
@selector(<#selector#>)//oc編譯器提供的
SEL NSSelectorFromString(NSString *aSelectorName)//OC字符串轉(zhuǎn)化
SEL method_getName ( Method m );//根據(jù)Method結(jié)構(gòu)體獲取
等等

SEL的操作函數(shù)

// 比較兩個選擇器
BOOL sel_isEqual ( SEL lhs, SEL rhs );
//判斷方法名是否映射到某個函數(shù)實現(xiàn)上
BOOL sel_isMapped(SEL sel);
出現(xiàn)個BUG:

既然SEL是方法的唯一標識鸿秆,那不同的類調(diào)用名字相同的方法怎么辦呢?

那就讓下一個重要任務出場吧怎囚。

IMP

定義:函數(shù)指針谬莹,指向方法實現(xiàn)的首地址。
代碼定義如下:

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

其參數(shù)包含id,SEL,后面試實際的參數(shù)列表桩了。
那么,XX調(diào)用了XXX方法埠戳,其參數(shù)為XX都確定下來了井誉。

IMP的高級作用

既然上述元素都確定下來了,那么就可以直接繞過Runtime的消息傳遞機制整胃,直接執(zhí)行IMP指向的函數(shù)了颗圣。省去了一些列的查找,直接向?qū)ο蟀l(fā)送消息,效率會高一些在岂。

IMP imp_implementationWithBlock(id block)//根據(jù)代碼塊獲取IMP,其實就是代碼塊與IMP關聯(lián)
IMP method_getImplementation(Method m) //根據(jù)Method獲取IMP
[[objc Class] instanceMethodForSelector:SEL]//根據(jù)OC方式獲取IMP

當我們獲取一個方法的IMP時候可以直接調(diào)用IMP

IMP imp = method_getImplementation(Method m)奔则;
id objc = imp(id,SEL,argument);//objc用來保存方法的返回值,id表示調(diào)用這個方法的對象蔽午,SEL是Method的選擇器易茬,argument是方法的參數(shù)。

Method

Method定義如下:它主要是用語描述類里面的方法

typedef struct objc_method *Method;

objc_method結(jié)構(gòu)體定義如下

struct objc_method {
    SEL method_name                              OBJC2_UNAVAILABLE;//方法名
    char *method_types                           OBJC2_UNAVAILABLE;//參數(shù)返回值字符串描述
    IMP method_imp                               OBJC2_UNAVAILABLE;//方法的實現(xiàn)
}    

從上述代碼可以看出及老,Method是一個結(jié)構(gòu)體抽莱,包含了SEL和IMP成員變量。
實際上骄恶,相當于在SEL和IMP之間做了一個映射食铐,有了Method,SEL就可以找到對應的IMP僧鲁,從而調(diào)用方法虐呻。

Method操作函數(shù)如下:
方法操作主要有以下函數(shù):
// 添加方法
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types );

// 獲取實例方法
Method class_getInstanceMethod ( Class cls, SEL name );

// 獲取類方法
Method class_getClassMethod ( Class cls, SEL name );

// 獲取所有方法的數(shù)組
Method * class_copyMethodList ( Class cls, unsigned int *outCount );

// 替代方法的實現(xiàn)
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );

// 返回方法的具體實現(xiàn)
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );

// 類實例是否響應指定的selector
BOOL class_respondsToSelector ( Class cls, SEL sel );

此處具體實現(xiàn)比較簡單,可以通過手動操作IMP來完成方法的調(diào)用寞秃。

實例代碼:

#import "OC_IMP.h"


typedef void (^CustomBlock)(NSString *name);

@interface OC_IMP ()

@property(nonatomic, weak) CustomBlock block;

@end

@implementation OC_IMP

- (void)testIMP {
    [self addMethodByIMP];
}

//定義一個block
//手動添加方法
- (void)addMethodByIMP {
    CustomBlock block = ^(NSString *name){
        NSLog(@"執(zhí)行block");
    };
    
    IMP impBlock = imp_implementationWithBlock(block);
    Method m = class_getInstanceMethod(self.class, @selector(testIMP));
    method_setImplementation(m, impBlock);
    const char * types = method_getTypeEncoding(m); //因為方法類型相同(都是無參數(shù)無返回值類型斟叼,所以方法類型相同,如果知道的話蜕该,可以直接制定type為v16@0:8)
    sel_registerName("newSel");             //注冊newSel
    BOOL isAdded = class_addMethod([self class], @selector(newSel), impBlock, types);
    if (isAdded == YES) {
        NSLog(@"添加成功");
        [self performSelector:@selector(newSel)];
    }
}

@end
    OC_IMP *oc_imp = [[OC_IMP alloc] init];
    [oc_imp testIMP];

調(diào)用執(zhí)行結(jié)果

2017-07-14 20:14:26.359 OCDeepLearning[5654:530015] 添加成功
2017-07-14 20:14:26.359 OCDeepLearning[5654:530015] 執(zhí)行block

補充:

  1. 在swift里可以使用#selector(XXX)來獲取對應的SEL,但這并非指swift的方法調(diào)用是通過selector來實現(xiàn)的犁柜,能調(diào)用僅僅是因為swift和OC的混編;
  2. 每個方法名有對應的唯一seletor,其SEL相同堂淡,但對應的IMP函數(shù)指針不同馋缅。

Github源碼地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市绢淀,隨后出現(xiàn)的幾起案子萤悴,更是在濱河造成了極大的恐慌,老刑警劉巖皆的,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件覆履,死亡現(xiàn)場離奇詭異,居然都是意外死亡费薄,警方通過查閱死者的電腦和手機硝全,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來楞抡,“玉大人伟众,你說我怎么就攤上這事≌偻ⅲ” “怎么了凳厢?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵账胧,是天一觀的道長。 經(jīng)常有香客問我先紫,道長治泥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任遮精,我火速辦了婚禮居夹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘仑鸥。我一直安慰自己吮播,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布眼俊。 她就那樣靜靜地躺著意狠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疮胖。 梳的紋絲不亂的頭發(fā)上环戈,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音澎灸,去河邊找鬼院塞。 笑死,一個胖子當著我的面吹牛性昭,可吹牛的內(nèi)容都是我干的拦止。 我是一名探鬼主播糜颠,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼其兴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起元旬,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匀归,沒想到半個月后坑资,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體穆端,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡盐茎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了徙赢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片字柠。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狡赐,靈堂內(nèi)的尸體忽然破棺而出窑业,到底是詐尸還是另有隱情,我是刑警寧澤枕屉,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布常柄,位于F島的核電站,受9級特大地震影響搀擂,放射性物質(zhì)發(fā)生泄漏西潘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一哨颂、第九天 我趴在偏房一處隱蔽的房頂上張望喷市。 院中可真熱鬧,春花似錦威恼、人聲如沸品姓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腹备。三九已至,卻和暖如春斤蔓,著一層夾襖步出監(jiān)牢的瞬間植酥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工弦牡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留友驮,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓喇伯,卻偏偏與公主長得像喊儡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子稻据,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉艾猜,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,709評論 0 9
  • 繼上Runtime梳理(四) 通過前面的學習,我們了解到Objective-C的動態(tài)特性:Objective-C不...
    小名一峰閱讀 752評論 0 3
  • 本文轉(zhuǎn)載自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex閱讀 758評論 0 1
  • 一捻悯、Runtime簡介 Runtime簡稱運行時匆赃。OC就是運行時機制,也就是在運行時候的一些機制今缚,其中最主要的是消...
    林安530閱讀 1,064評論 0 2
  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡介 Runt...
    樂樂的簡書閱讀 2,135評論 0 9