最近開始用
CTMetidor
來做App模組化
,順便研究一下它的實現原理
CTMetidor
原始碼中經常出現如下關鍵詞:NSSelectorFromString
、NSClassFromString
、SEL
這些是個啥???
在理解CTMediator原理之前我們先弄懂這麼幾個概念:
Method
先來看一下Method相關的定義
typedef struct objc_method *Method
struct objc_method{
SEL method_name OBJC2_UNAVAILABLE; // 方法名
char *method_types OBJC2_UNAVAILABLE; // 函式的返回值和引數
IMP method_imp OBJC2_UNAVAILABLE; // 方法的具體實現
}
複製程式碼
我們可以看到該結構體中包含一個SEL
和IMP
,實際上相當於在SEL
和IMP
之間作了一個對映,將SEL
和IMP
進行了關聯,通過SEL
我們便可以找到對應的IMP
,從而呼叫方法的實現程式碼。
SEL(selector)
-
方法編號,對方法名hash化的字串
-
無論什麼類裡,只要方法名相同,
SEL
就相同。專案裡的所有SEL
都儲存在一個NSSet集合裡(NSSet集合裡的元素不能重複),所以查詢對應方法,只要找到對應的SEL
就可以了。
既然SEL是方法的唯一標識,那不同的類呼叫名字相同的方法怎麼辦呢?
每個方法名有對應的唯一seletor,其
SEL
相同,但對應的IMP
函式指標不同。
如何獲取SEL?
SEL s1 = @selector(test);
SEL s2 = NSSelectorFromString(@“test”)
複製程式碼
以上兩個方法是等價的
IMP (implement)
- 一個函式指標,儲存了方法的地址,內部實現:
typedef id (*IMP)(id, SEL, ...);
複製程式碼
- 包含
id
(訊息接受者,也就是物件),SEL
(方法的名字),引數
XX呼叫XXX方法,引數XX也都確定了
執行對應的方法:
[object test];
// @selector(test) 是一個C的字串
[object performSelector:@selector(test)]];
// 轉換成如下實現方式
objc_msgSend(object,@selector(test))
複製程式碼
總結
- NSClassFromString 通過字串的名稱來獲取一個類,可以根據Target來進行獲取
- NSSelectorFromString 通過字串(已存在的方法名稱)獲取一個SEL