NSObject爲全部類的根類,它位於整個類層次的根上,類層次中的全部其它類最終都是從根類繼承而來。(萬物皆NSObject)bash
咱們知道全部的類均可以用class接收,因此咱們建立一個類對象app
Person *person = [Person alloc];
Class pClass = object_getClass(person);
複製代碼
查看Class源碼:ui
typedef struct objc_class *Class;
複製代碼
查看objc_class源碼:this
struct objc_class : objc_object {
// Class ISA;
Class superclass; //
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
// 下面是一些方法
class_rw_t *data() {
return bits.data();
}
…
}
複製代碼
objc_class中的Class ISA屬性繼承自父類 objc_object,查看objc_object源碼:atom
struct objc_object {
private:
isa_t isa;
…
}
複製代碼
???、objc_object與NSObject有什麼關係呢? 咱們再來看NSObject的源碼定義:spa
NSObject的源碼定義:
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
複製代碼
其實他們是同一個事物的不一樣表現形式。objc_object爲c結構體寫法,而NSObject爲OC寫法。3d
咱們爲類對象添加成員變量、屬性和實例方法、類方法:調試
@interface Person : NSObject{
NSString *hobby;
}
@property (nonatomic, copy) NSString *nickName;
- (void)sayHello;
+ (void)sayHappy;
@end
複製代碼
首先咱們查看objc_class源碼中的方法:code
class_rw_t *data() {
return bits.data();
}
複製代碼
查看class_rw_t,surprise:orm
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint32_t version;
//———————————重點—————————————
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
//——————————————————————————
Class firstSubclass;
Class nextSiblingClass;
char *demangledName;
#if SUPPORT_INDEXED_ISA
uint32_t index;
#endif
…
};
複製代碼
因此咱們要找的東西就在這個class_rw_t裏面。
接下來咱們開始lldb調試:
咱們須要class_data_bits_t bits的地址:Class ISA(8個字節)+ Class superclass(8個字節)+ cache_t cache(?)
仍是查看源碼:
typedef uint32_t mask_t; // 4
struct cache_t {
struct bucket_t *_buckets; // 8
mask_t _mask; // 4
mask_t _occupied; // 4
…
}
複製代碼
得出: Class ISA(8個字節)+ Class superclass(8個字節)+ cache_t cache(16個字節),即偏移0x20個字節。
查看它的const class_ro_t *ro參數:實例方法一樣存在於baseMethodList中
咱們會發現,在class_data_bits_t裏面,是不管如何都找不到類方法的,怎麼辦呢?咱們只能去它的元類裏面查看。定義一個方法:
void testInstanceMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));
Method method3 = class_getInstanceMethod(pClass, @selector(sayByeBye));
Method method4 = class_getInstanceMethod(metaClass, @selector(sayByeBye));
NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);
}
複製代碼
打印結果:
0x100002248-0x0-0x0-0x1000021e0
印證了咱們的想法,類方法確實存在於它的元類裏面。