在我們iOS開發(fā)過程中遇到很多@selector
夜涕,特別是在按鈕點擊事件中都有@selector()
這個方法秦士,下面簡單地說下@selector
的實現(xiàn)以及簡單原理 片任。
先看下官方文檔
SEL aSelector = @selector(run);
[aDog performSelector:aSelector];
第一步:將方法包裝成@SEL
第二步:然后在類中查找方法列表
第三步:根據(jù)@SEL找到imp指針(函數(shù)指針)
第四步:執(zhí)行函數(shù)
SEL 類他的行為相當(dāng)于 C 語言中的函數(shù)指針贮折,因為在 C 語言中锹锰,可以把函數(shù)名直接賦給一個函數(shù)指針掏导,而ObjC的類不能直接應(yīng)用函數(shù)指針享怀,這樣只能做一個@selector語法來取。
SEL消息機制工作原理
大家應(yīng)該都知道,一個類就像一個 C 結(jié)構(gòu).NSObject
聲明了一個成員變量: isa
. 由于 NSObject
是所有類的根類,所以所有的對象都會有一個isa
的成員變量[公共繼承].而該isa
變量指向該對象的類[類在Objective-C中也是一個實體, 由于存在Objective-C 運行環(huán)境所有的類將有自己的存儲空間.Objective-C 運行環(huán)境將為每個類分配空間. 這里 所說的 isa,正是指向這樣一個類的空間. 從而建立類和對象之間的對應(yīng)關(guān)系.] 類空間 包含了該類定義的成員變量,以及方法實現(xiàn), 還包含了指向自己父類空間的指針.
方法以 selector
作為索引趟咆。selector
的數(shù)據(jù)類型是 SEL添瓷, 雖然 SEL 定義成 char*
, 我們可 以把它想象成int
. 每個方法的名字對應(yīng)一個唯一的int
值.比如, 方法 addObject:
可能 對應(yīng)的是 12. 當(dāng)尋找該方法是, 使用的是 selector,而不是名字 @"addObject:"
Objective-C 數(shù)據(jù)結(jié)構(gòu)中,存在一個 name - selector
的映射表如圖
在編譯的時候, 只要有方法的調(diào)用, 編譯器都會通過 selector 來查找,所以 (假設(shè) addObject 的 selector 為 12)
[myObject addObject:yourObject];
將會編譯變成
objc_msgSend(myObject, 12, yourObject);
這里objec_msgSend()
函數(shù)將會使用 myObjec
的 isa 指針來找到 myObject
的類空間結(jié)構(gòu)并 在類空間結(jié)構(gòu)中查找 selector 12
所對應(yīng)的方法.如果沒有找到,那么將使用指向父類的指 針找到父類空間結(jié)構(gòu)進行 selector 12
的查找. 如果仍然沒有找到,就繼續(xù)往父類的父類一 直找,直到找到為止, 如果到了根類NSObject
中仍然找不到,將會拋出異常。
有問題歡迎討論值纱,我的微博@A1saka
不喜勿噴鳞贷,謝謝!计雌!