CTMediator 原理詳解(一)

LuckyRoc發表於2019-01-07

最近開始用CTMetidor來做App模組化,順便研究一下它的實現原理

CTMetidor 原始碼中經常出現如下關鍵詞:NSSelectorFromStringNSClassFromStringSEL 這些是個啥???

在理解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; // 方法的具體實現
}
複製程式碼

CTMediator 原理詳解(一)

我們可以看到該結構體中包含一個SELIMP,實際上相當於在SELIMP之間作了一個對映,將SELIMP進行了關聯,通過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

相關文章