首先,我們都知道NSObject是大多數類的根類,但是,這個類的是怎麼實現的呢?我們可以去下載開源的Runtime源碼,探究下NSObject類的實現。 1. NSObject.h文件 我們可以直接使用Command點NSOject進去看到它的頭文件,可以看到,NSObject.h文件中有兩塊內容: ...
首先,我們都知道NSObject是大多數類的根類,但是,這個類的是怎麼實現的呢?我們可以去下載開源的Runtime源碼,探究下NSObject類的實現。
1. NSObject.h文件
我們可以直接使用Command點NSOject進去看到它的頭文件,可以看到,NSObject.h文件中有兩塊內容:
- NSObject 協議
- NSObject 實現
1.1 NSObject 協議
@protocol NSObject - (BOOL)isEqual:(id)object; @property (readonly) NSUInteger hash; @property (readonly) Class superclass; - (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead"); - (instancetype)self; - (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; - (BOOL)isKindOfClass:(Class)aClass; - (BOOL)isMemberOfClass:(Class)aClass; - (BOOL)conformsToProtocol:(Protocol *)aProtocol; @end
這裡只是粘貼了部分方法,其中也有很多我們熟悉的方法,比如判斷代理是否實現某個方法,實現某個協議等等,這個也就解釋了,為什麼我們自定義的協議也要遵循NSObject的協議,我們可以直接使用NSObject協議中的方法,去判斷代理是否實現了,因為協議有Optional這個關鍵字,協議的方法是可選實現的。
1.2 NSObject的成員變數
我們還是在NSObject.h文件中,可以看到,NSObject只有一個成員變數是Class類型的isa變數:
@interface Object { Class isa; /* A pointer to the instance's class structure */ }
那麼Class類型是什麼類型呢?我們可以大概的猜想一下,可能就是指它所屬的類吧。
Now,我們Command繼續看這個Class的實現。
1.3 Class是什麼玩意?
typedef struct objc_class *Class;
簡單明瞭,Class就是一個指向結構體的指針。關於這一塊,不明白結構體指針的,還需要去補充一下這方面的知識。然後,我們繼續看 objc_class 這個結構體:
struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY; // 還是那個指針 #if !__OBJC2__ Class _Nullable super_class // 父類 OBJC2_UNAVAILABLE; const char * _Nonnull name // 類名 OBJC2_UNAVAILABLE; long version // 版本 OBJC2_UNAVAILABLE; long info // 包含信息 OBJC2_UNAVAILABLE; long instance_size // 成員變數的size? OBJC2_UNAVAILABLE; struct objc_ivar_list * _Nullable ivars // 成員變數存儲list OBJC2_UNAVAILABLE; struct objc_method_list * _Nullable * _Nullable methodLists // 類中的方法 OBJC2_UNAVAILABLE; struct objc_cache * _Nonnull cache // 類中的方法緩存 OBJC2_UNAVAILABLE; struct objc_protocol_list * _Nullable protocols // 類中的協議列表 OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
我們這裡先看下isa指針:
- isa:在這個結構體中我們看到也有一個isa指針,這個isa指針指向的是meta class,這裡補充一下,類其實也是一個對象就是類對象。
搞到這裡有點暈了,我們可以看下id類型是個啥類型,可以對比一下。
1.4 id類型
struct objc_object { Class _Nonnull isa OBJC_ISA_AVAILABILITY; }; /// A pointer to an instance of a class. typedef struct objc_object *id;
我們可以發現,id類型其實也是一個結構體指針啊,這裡我們可以看到,objc_object 這個結構體中也有一個 isa變數。So,我們在NSObject,objc_class,objc_object中看到都有一個objc_class *類型,也就是Class類型的變數isa,可見這個isa是多麼的重要啊。
我們可以得到大概這樣的結論,在objc的runtime中,類是用objc_class結構體表示的,對象是用objc_object結構體表示的,對象的isa用來標示這個對象是哪一個類的實例。我們可以通過幾個方法來驗證一下。
2. NSObject.m
我們經常使用的判斷一個對象是不是某個類或這個類的派生類的實例,那麼我們就去看一下這兩個方法的實現
- (Class)class { return object_getClass(self); } Class object_getClass(id obj){ if (obj) return obj->getIsa(); else return Nil; } - (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls; }
上面的三個方法簡單明瞭,我們在判斷一個對象是否是某個類的實例時,其實就是看這個對象中的isa指針是否指向某個類,當我們調用self class方法時,其實也就是拿到這個實例對象的isa指針,也就是指向結構體objc_class的指針,然後進行判斷返回結果。所以,我們可以知道,對於某個普通的對象實例,通過調用[object class]其實返回的就是這個實例的isa變數。
一個類的實例對象的isa指針指向的是這個對象所屬的類,這個類描述了一系列它的實例的特點,就像上面的objc_class結構體中的成員變數列表,成員函數的列表等。這個對象能夠接受的消息列表也是存儲在這個類中。
下麵我們也分析一下objc_class,為什麼也有一個isa變數呢?
在面向對象的世界中,萬物皆對象,所以,類也是一個對象:類對象。它也有一個isa指針,那麼它指向誰呢?我們可以看下 +Class方法的實現:
+ (Class)class { return self; }
為什麼返回的竟然是self呢?我們知道對於某個類的實例來說,self總是指向其自身的,但是這裡並沒有實例啊,我們是直接調用了這個類的類方法啊,難道類本身也有一個self指針?這個方法的返回值是一個類對象,所以其本質還是一個對象。對於NSObject這樣的類來說,它其實也就代表一個類對象,類對象的self指針應該指向的也是這個類對象自身。