Objective-C 中 NSObject是大多數類的根類。
@interface NSObject {
Class isa OBJC_ISA_AVAILABILITY;
}
它有一個isa屬性,類型是Class.
蘋果已經將 ObjC runtime 代碼開源了,我們下載下,看看Class到底是什麼http://opensource.apple.com/tarballs/objc4/objc4-493.9.tar.gz
我們可以在
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
Class 是一個 objc_class 結構類型的指針, id是一個 objc_object 結構類型的指針.
objc_class的定義可以在
struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
} OBJC2_UNAVAILABLE;
接下來我們來看下每個屬性的意思
是一個 Objective-C Class 類型的指針. 實例對象有個isa的屬性,指向Class, 而Class裡也有個isa的屬性, 指向meteClass. 這裡就有個點, 在Objective-C中任何的類定義都是對象.
指向該類的父類, 如果該類已經是最頂層的根類(如 NSObject 或 NSProxy),那麼 super_class 就為 NULL.
他們的關系呢,這裡有個圖http://www.sealiesoftware.com/blog/class%20diagram.pdf
我們先看下下面的代碼
id objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
PRIVATE_EXTERN id look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler)
{
BOOL includeClassLoader = YES; // class loader cannot be skipped
id result = nil;
struct old_class query;
query.name = aClassName;
retry:
if (!result && class_hash) {
// Check ordinary classes
mutex_lock (&classLock);
result = (id)NXHashGet(class_hash, &query);
mutex_unlock (&classLock);
}
if (!result && includeUnconnected && unconnected_class_hash) {
// Check not-yet-connected classes
mutex_lock(&classLock);
result = (id)NXHashGet(unconnected_class_hash, &query);
mutex_unlock(&classLock);
}
if (!result && includeClassLoader && _objc_classLoader) {
// Try class loader callback
if ((*_objc_classLoader)(aClassName)) {
// Re-try lookup without class loader
includeClassLoader = NO;
goto retry;
}
}
if (!result && includeClassHandler && objc_classHandler) {
// Try class handler callback
if ((*objc_classHandler)(aClassName)) {
// Re-try lookup without class handler or class loader
includeClassLoader = NO;
includeClassHandler = NO;
goto retry;
}
}
return result;
}
struct old_class {
struct old_class *isa;
struct old_class *super_class;
const char *name;
long version;
long info;
long instance_size;
struct old_ivar_list *ivars;
struct old_method_list **methodLists;
Cache cache;
struct old_protocol_list *protocols;
// CLS_EXT only
const uint8_t *ivar_layout;
struct old_class_ext *ext;
};
objc_getClass從一個字串返回一個類,look_up_class,先創建一個old_class對象,name賦值為這個字串,如果找到了,就返回old_class.看下old_class的結構就能看出name這個屬性存的值就是類的名字(其實name不就是名字嘛)
類的版本信息,默認為0
供運行期使用的一些位標識。
該類的實例變量大小
struct objc_ivar_list {
int ivar_count;
/* variable length structure */
struct objc_ivar ivar_list[1];
}
成員變量的數組
方法定義的數組
struct objc_method_list {
struct objc_method_list *obsolete;
int method_count;
/* variable length structure */
struct objc_method method_list[1];
}
指向最近使用的方法.用於方法調用的優化.
struct objc_cache {
unsigned int mask /* total = mask + 1 */;
unsigned int occupied;
Method buckets[1];
};
協議的數組
struct objc_protocol_list {
struct objc_protocol_list *next;
long count;
Protocol *list[1];
};