iOS Sharing #01 | 2019-03-23

目錄

一、Runtime存在的意義是什麼?

二、根元類的isa指針指向誰?

三、根元類的superClass指針指向誰?

四、函數四要素都是什麼?

五、實例方法去哪裏找?


一、Runtime存在的意義是什麼?

答:Objective-C 是一門動態語言,它會將一些工做放在代碼運行時才處理而並不是編譯時。也就是說,有不少類和成員變量在咱們編譯的時是不知道的,而在運行時,咱們所編寫的代碼會轉換成完整的肯定的代碼運行。所以,只有編譯器是不夠的,咱們還須要一個運行時系統(Runtime system)來處理編譯後的代碼。 這就是 Objective-C Runtime 系統存在的意義,它是整個Objc運行框架的一塊基石。

平時編寫的OC代碼,底層都是由他實現的,如:git

[receiver message];
//底層運行時會被編譯器轉化爲:
objc_msgSend(receiver, selector)
//若是其還有參數好比:
[receiver message:(id)arg...];
//底層運行時會被編譯器轉化爲:
objc_msgSend(receiver, selector, arg1, arg2, ...)

複製代碼

二、根元類的isa指針指向誰?

答: 見下一問

三、根元類的superClass指針指向誰?

答:這兩題一塊兒回答。首先看下圖:

nsobject

先說幾個概念:
1)supercalss : 父類
2)subclass: 子類
3)isa : 概念很差說,官方文檔說的也不清晰。做用是根據 isa 指針就能夠找到對象所屬的類,可是isa指針在代碼運行時並不總指向實例對象所屬的類型,因此不能依靠它來肯定類型,要想肯定類型仍是須要用對象的 -class 方法。(PS:KVO 的實現機理就是將被觀察對象的isa指針指向一箇中間類而不是真實類型。)
4)class : 類,一個運行時類中關聯了它的父類指針、類名、成員變量、方法、緩存以及附屬的協議。(一個實例對象是一個類的實例)
5)meta class :元類,Objc 類自己也是一個對象 ,類對象所屬的類就叫作元類(一個類是元類的實例)
github

第一列是類的實例變量,如:[Person new]或者[[Person alloc] init]出來的對象;
第二列是類自己,存放父類指針、類名、成員變量、方法、緩存以及附屬的協議的信息;
第三列是元類
緩存

  • 1)isa路線:
    • 實例對象的isa指向Class
    • Class的isa指向Meta Class
    • Meta Class的isa指向根元類Root Meta Class
    • 根元類的isa指向本身
  • 2)superclass路線:
    • 實例對象沒有superclass ;
    • 實例對象所在的類,存在superclass,類的superclass後面會指向Root Class,Root Class的super Class是nil;
    • 元類也存在superclass,元類的superclass後面會指向Root Meta Class,而Root Meta Class的superclass倒是Root Class。

因此:數據結構

  • 根元類的isa指針指向本身
  • 根元類的superclass指向root class
  • 根類的isa指向根元類
  • 根類的superclass指向nil

附舊版Class結構:app

typedef struct objc_class *Class;
Class 實際上是指向 objc_class 結構體的指針。objc_class 的數據結構以下:
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;

複製代碼
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// A pointer to an instance of a class.
typedef struct objc_object *id;

複製代碼
  • Class是一個指向objc_class(類)結構體的指針,而id是一個指向objc_object(對象)結構體的指針。框架

  • objec_object(對象)中isa指針指向的類結構稱爲objec_class(該對象的類),其中存放着普通成員變量與對象方法 (「-」開頭的方法)。函數

  • objec_class(類)中isa指針指向的類結構稱爲metaclass(該類的元類),其中存放着static類型的成員變量與static類型的方法 (「+」開頭的方法)。spa

附圖:
舊版Class 3d

objc-old
新版Class

objc-new


四、函數四要素都是什麼?

答:函數名,函數參數,參數類型,返回值類型(PS:ObjC通常叫方法,不叫函數)

OC method簡單介紹

typedef struct objc_method *Method;
struct objc_method {
    SEL method_name OBJC2_UNAVAILABLE;  //方法名
    char *method_types OBJC2_UNAVAILABLE;   //方法類型
    IMP method_imp OBJC2_UNAVAILABLE;   //方法實現
}
複製代碼

objc_method 存儲了方法名,方法類型和方法實現。指針

方法名類型爲 SEL

方法類型 method_types 是個 char 指針,存儲方法的參數類型和返回值類型 method_imp 指向了方法的實現,本質是一個函數指針 Ivar Ivar 是表示成員變量的類型。

typedef struct objc_ivar *Ivar;
struct objc_ivar {
    char *ivar_name OBJC2_UNAVAILABLE;
    char *ivar_type OBJC2_UNAVAILABLE;
    int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space OBJC2_UNAVAILABLE;
#endif
}
複製代碼

其中 ivar_offset 是基地址偏移字節

IMP

IMP在objc.h中的定義是:

typedef id (*IMP)(id, SEL, ...);
複製代碼

它就是一個函數指針,這是由編譯器生成的。當你發起一個 ObjC 消息以後,最終它會執行的那段代碼,就是由這個函數指針指定的,而 IMP 這個函數指針就指向了這個方法的實現。


五、實例方法去哪裏找?

答:其所屬的類的方法表

拓展

問:oc是如何找到須要執行哪一個方法的?
答:當須要執行某個實例方法的時候(類方法相似),oc會先去該類的方法的緩存列表裏面查找,若找到了,則執行,不然,去該類的方法列表中查找是否存在該方法,存在,執行該方法並更新方法緩存列表,不然,去該父類緩存以及父類方法列表查找,直到根類,若還未找到,則啓用動態解析以及消息轉發流程,若仍是失敗,報unrecognized selector異常

詳細流程
感謝大佬提供的流程圖


倉庫

本篇相關代碼


聯繫方式

郵箱: adrenine@163.com

郵箱: holaux@gmail.com

郵箱: ledahapple@icloud.com

相關文章
相關標籤/搜索