关于SEL的一些总结
1.SEL的概述
SEL就是對(duì)方法的一種包裝,是表示一個(gè)方法的selector的指針。包裝的SEL類型數(shù)據(jù)它對(duì)應(yīng)相應(yīng)的方法地址,找到方法地址就可以調(diào)用方法,其定義如下:
objc_selector結(jié)構(gòu)體的詳細(xì)定義沒有在頭文件中找到。方法的selector用于表示運(yùn)行時(shí)方法的名字。Objective-C在編譯時(shí),會(huì)依據(jù)每一個(gè)方法的名字、參數(shù)序列,生成一個(gè)唯一的整型標(biāo)識(shí)(Int類型的地址),這個(gè)標(biāo)識(shí)就是SEL。不用的類里面的相同名字相同聲明的方法的身份證明是一樣的。這樣在程序執(zhí)行的時(shí)候,runtime就不用費(fèi)力的進(jìn)行方法的名字比較來確定是執(zhí)行哪一個(gè)方法了,只是通過一個(gè)整數(shù)的尋找就可以馬上定位到相應(yīng)的方法,然后找到相應(yīng)的方法的入口地址,這樣方法就可以被執(zhí)行了。
示例代碼:
ViewController.m
#import "ViewController.h" #import "Selector.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.Selector * select =[[Selector alloc]init];[select performSelector:@selector(viewDidLoad) withObject:nil];SEL sel1 =@selector(viewDidLoad);NSLog(@"sel1:%p",sel1);NSLog(@"viewDidLoad:%p",_cmd);//_cmd本身代表所在方法的SEL } @end Selector.m #import "Selector.h" @implementation Selector - (void)viewDidLoad {NSLog(@"Selector:%p",_cmd); } @end上面的輸出為:
2016-04-27 11:37:53.883 SEL? @selector()[6278:61711] Selector:0x106f674d5
2016-04-27 11:37:53.884 SEL? @selector()[6278:61711] sel1:0x106f674d5
2016-04-27 11:37:53.884 SEL? @selector()[6278:61711] viewDidLoad:0x106f674d5
注意點(diǎn):
兩個(gè)類之間,不管它們是父類與子類的關(guān)系,還是之間沒有這種關(guān)系,只要方法名相同,那么方法的SEL就是一樣的。每一個(gè)方法都對(duì)應(yīng)著一個(gè)SEL。所以在 Objective-C同一個(gè)類(及類的繼承體系)中,不能存在2個(gè)同名的方法,即使參數(shù)類型不同也不行。相同的方法只能對(duì)應(yīng)一個(gè)SEL。這也就導(dǎo)致 Objective-C在處理相同方法名且參數(shù)個(gè)數(shù)相同但類型不同的方法方面的能力很差。如在某個(gè)類中定義以下兩個(gè)方法:
- (void)setWidth:(int)width;- (void)setWidth:(double)width;
當(dāng)然,不同的類可以擁有相同的selector,這個(gè)沒有問題。不同類的實(shí)例對(duì)象執(zhí)行相同的selector時(shí),會(huì)在各自的方法列表中去根據(jù)selector去尋找自己對(duì)應(yīng)的IMP。
2.SEL的理解
工程中的所有的SEL組成一個(gè)Set集合,Set的特點(diǎn)就是唯一,因此SEL是唯一的。因此,如果我們想到這個(gè)方法集合中查找某個(gè)方法時(shí),只需要去找到這個(gè)方法對(duì)應(yīng)的SEL就行了,SEL實(shí)際上就是根據(jù)方法名hash化了的一個(gè)字符串,而對(duì)于字符串的比較僅僅需要比較他們的地址就可以了,可以說速度 上無語倫比!!但是,有一個(gè)問題,就是數(shù)量增多會(huì)增大hash沖突而導(dǎo)致的性能下降(或是沒有沖突,因?yàn)橐部赡苡玫氖莗erfect hash)。但是不管使用什么樣的方法加速,如果能夠?qū)⒖偭繙p少(多個(gè)方法可能對(duì)應(yīng)同一個(gè)SEL),那將是最犀利的方法。那么,我們就不難理解,為什么 SEL僅僅是函數(shù)名了。
本質(zhì)上,SEL只是一個(gè)指向方法的指針(準(zhǔn)確的說,只是一個(gè)根據(jù)方法名hash化了的KEY值,能唯一代表一個(gè)方法),它的存在只是為了加快方法的查詢速度。這個(gè)查找過程我們將在下面討論。
我們可以在運(yùn)行時(shí)添加新的selector,也可以在運(yùn)行時(shí)獲取已存在的selector,
我們可以通過下面三種方法來獲取SEL:
1. sel_registerName函數(shù)2. Objective-C編譯器提供的@selector()
3. NSSelectorFromString()方法
SEL的用法主要有一下幾種
1.SEL 變量名 = @selector(方法名字); //注意有參數(shù)時(shí)要帶上:
2.SEL 變量名 = NSSelectorFromString(方法名字的字符串);
3.NSString *變量名 = NSStringFromSelector(SEL參數(shù));
參考:
? 1.http://www.cnblogs.com/yaski/archive/2009/04/05/1429735.html
總結(jié)
以上是生活随笔為你收集整理的关于SEL的一些总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何更改文件夹图标和颜色
- 下一篇: RFC 文档中文目录