實例方法
和類方法
的存儲位置:
- 實例方法:每個實例的
isa
指針指向著對應(yīng)類對象劲绪,而每一個類對象中都一個對象方法列表。- 類方法:每個類對象的
isa
指針都指向著對應(yīng)的元類對象卡者,而每一個元類對象中都有一個類方法列表蒿囤。
- 當我們發(fā)送一個消息給一個
NSObject
對象時,這條消息會在對象的類對象方法列表里查找崇决。- 當我們發(fā)送一個消息給一個類時材诽,這條消息會在類的
meta class
對象的方法列表里查找底挫。
- 方法列表中記錄著一個個方法實體(結(jié)構(gòu)體
Method
),實體中包含方法的名稱脸侥,方法實現(xiàn)建邓,以及參數(shù)類型。 - 其實
selector
本質(zhì)就是C字符串的方法名稱(見下面分析)湿痢,通過這個方法名稱就可以在方法列表中找到方法實體涝缝,進一步找到對應(yīng)的方法實現(xiàn)扑庞。
Selector譬重,Method 和 IMP 的區(qū)別與聯(lián)系
Selector
定義:
typedef struct objc_selector *SEL
翻譯成中文叫做選擇子或者選擇器,選擇子代表方法在Runtime
期間的標識符罐氨。為SEL
類型臀规,雖然SEL
是objc_selector
結(jié)構(gòu)體指針,但實際上它只是一個C字符串
栅隐。在類加載的時候塔嬉,編譯器會生成與方法相對應(yīng)的選擇子,并注冊到Objective-C
的Runtime
運行系統(tǒng)租悄。
常見的有兩種方式來獲取/創(chuàng)建選擇子:
SEL selA = @selector(setString:);
SEL selB = sel_registerName("setString:");
在控制臺測試:
(lldb) p selA
(SEL) $1 = "setString:"
(lldb) p selB
(SEL) $2 = "setString:"
兩者打印出來的都是字符串谨究。
我們從sel_getName()
方法的源碼可以看出SEL
和const char *
是可以相互轉(zhuǎn)化的:
const char *sel_getName(SEL sel) {
return sel ? (const char *)sel : "<null selector>";
}
如果將selA
和selB
強轉(zhuǎn)為為const char *
:
(lldb) p (const char *)$2
(const char *) $3 = 0x00007fff9a3794b5 "setString:"
(lldb) p (const char *)$1
(const char *) $4 = 0x00007fff9a3794b5 "setString:"
(lldb)
上面的結(jié)果可以看出,selA
和selB
指向相同的地址泣棋,代表同一個字符串胶哲。
如果某個類實現(xiàn)了setString:
方法,那么以上兩個選擇子傳入 respondsToSelector()
方法返回的結(jié)果都將為YES
潭辈。
不同類中相同名字的方法所對應(yīng)的方法選擇子是相同的鸯屿。
Implementation(IMP):
定義:
typedef id (*IMP)(id, SEL, ...)
代表函數(shù)指針,即函數(shù)執(zhí)行的入口把敢。該函數(shù)使用標準的C
調(diào)用寄摆。
- 第一個參數(shù)指向
self
(它代表當前類實例的地址,如果是類則指向的是它的元類)修赞,作為消息的接受者婶恼; - 第二個參數(shù)代表方法的選擇子;
-
...
代表可選參數(shù)柏副; - 前面的
id
代表返回值熙尉。
Method
定義:
typedef struct objc_method *Method
Method 對開發(fā)者來說是一種不透明的類型,它是一個objc_method
結(jié)構(gòu)體指針搓扯,objc_method
的定義為:
/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;
struct objc_method {
SEL method_name; // 方法選擇器检痰。
char *method_types; // 存儲著方法的參數(shù)類型和返回值類型。
IMP method_imp; // 函數(shù)指針锨推。
}
- 方法名
method_name
類型為SEL
,前面提到過相同名字的方法即使在不同類中定義换薄,它們的方法選擇器也相同踢京; - 方法類
method_types
是個char
指針,其實存儲著方法的參數(shù)類型和返回值類型厦幅,即是Type Encoding
編碼; -
method_imp
指向方法的實現(xiàn)慨飘,本質(zhì)上是一個函數(shù)的指針确憨,就是前面講到的Implementation
。
Selector
瓤的,Method
休弃,IMP
它們之間的關(guān)系可以這么解釋:
一個類(Class
)持有一個方法列表,在運行期分發(fā)消息圈膏,表中的每一個實體代表一個方法(Method
)塔猾,它的名字叫做選擇子(SEL
),對應(yīng)著一種方法實現(xiàn)(IMP
)稽坤。