runtime-objc 类结构

运行时特性
Objectiv-C = C + Preprocessor(预处理器) + runtime
编译器Clang把OC代码编译成C++代码
运行时系统Runtime,执行编译后的代码

核心功能
c结构体->封装 -> OC类
执行OC方法 ->消息机制 ->执行C函数
编译OC文件
clang -rewrite-objc Person.m
runtime 源码
apple source:
https://opensource.apple.com/source/bojc4/
强制转换(
((void()(id,SEL,int))(void)objc_mesgSend)
//通过这个设置可以进行objc_mesgSend直接调用 不用转换
Build Settings -> Enable Strict Checking of objc_msgSend Calls -> NO

类的结构

 struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY; //类中isa

#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                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                OBJC2_UNAVAILABLE;  //属性
    struct objc_method_list * _Nullable * _Nullable methodList    OBJC2_UNAVAILABLE; //方法
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE; //方法
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE; //协议列表
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

类中的rw

struct class_rw_ext_t {
    const class_ro_t *ro;
    method_array_t methods; //方法列表
    property_array_t properties; //属性类别
    protocol_array_t protocols; //协议列表
    char *demangledName;
    uint32_t version;
};

类中的ro

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

方法结构体

struct method_t {
    SEL name; //方法名
    const char *types;//方法类型
    MethodListIMP imp;//方法地址

    struct SortBySELAddress :
        public std::binary_function<const method_t&,
                                    const method_t&, bool>
    {
        bool operator() (const method_t& lhs,
                         const method_t& rhs)
        { return lhs.name < rhs.name; }
    };
};

协议列表

struct protocol_list_t {
    // count is pointer-sized by accident.
    uintptr_t count;
    protocol_ref_t list[0]; // variable-size

    size_t byteSize() const {
        return sizeof(*this) + count*sizeof(list[0]);
    }

};
struct protocol_t : objc_object {
    const char *mangledName; //协议名
    struct protocol_list_t *protocols; //协议列表
    method_list_t *instanceMethods;//实例方法
    method_list_t *classMethods; //类方法
    method_list_t *optionalInstanceMethods;//可选实例方法
    method_list_t *optionalClassMethods;//可选类方法
    property_list_t *instanceProperties;//实例属性
    uint32_t size;   // sizeof(protocol_t)
    uint32_t flags;
    // Fields below this point are not always present on disk.
    const char **_extendedMethodTypes;
    const char *_demangledName;
    property_list_t *_classProperties;

    const char *demangledName();

    const char *nameForLogging() {
        return demangledName();
    }
}

属性列表

class property_array_t : 
    public list_array_tt<property_t, property_list_t> 
{
    typedef list_array_tt<property_t, property_list_t> Super;

 public:
    property_array_t() : Super() { }
    property_array_t(property_list_t *l) : Super(l) { }

    property_array_t duplicate() {
        return Super::duplicate<property_array_t>();
    }
};

struct property_t {
    const char *name; //属性名
    const char *attributes;//属性内容:strong weak 编码等
};

类的结构

image

验证上面这个经典的类的结构模型
//创建一个person类并在方法中做出下列打印

    NSLog(@"Person 实例对象的地址:%@",self);//实例对象
    Class myclass = objc_getClass("CFPerson");//类对象
    NSLog(@"Person 的类地址:%p",myclass);
    Class metaClass = objc_getMetaClass("CFPerson");//元类对象的地址
    NSLog(@"Person 的元类地址:%p",metaClass);
    Class superClass = class_getSuperclass(myclass);//父类对象
    NSLog(@"Person 父类的地址:%@:%p",superClass,superClass);
    NSObject *obj = [NSObject new];//NSObject 实例对象
    NSLog(@"NSObject实例对象地址:%p",obj);
    Class objClass = objc_getClass("NSObject"); //类对象
    NSLog(@"NSObject 的类地址:%p",objClass);
    Class objMetaClass = objc_getMetaClass("NSObject");
    NSLog(@"NSObject 的元类地址:%p",objMetaClass); //元类对象的地址
    //父类对象
    Class objSuperClass = class_getSuperclass(objClass);
    NSLog(@"NSObject 父类的地址:%@:%p",objSuperClass,objSuperClass);
    //元类对象的父类的地址 应该是NSObject 的地址
    Class objMetaSuperClass = class_getSuperclass(objMetaClass);
    NSLog(@"objMetaSuperClass 的元类地址:%p",objMetaSuperClass);
    NSLog(@"---------");
    NSLog(@"@Person实例的isa:%p",object_getClass(self));
    NSLog(@"Person类的isa:%p",object_getClass(myclass));
    NSLog(@"Person元类的isa:%p",object_getClass(metaClass));
    
    NSLog(@"@NSObject实例的isa:%p",object_getClass(obj));
    NSLog(@"NSObject类的isa:%p",object_getClass(objClass));
    NSLog(@"NSObject元类的isa:%p",object_getClass(objMetaClass));

看先打印结果:

Person 实例对象的地址:<CFPerson: 0x1032948d0>
Person 的类地址:0x100008138
Person 的元类地址:0x100008110
Person 父类的地址:NSObject:0x7fff993fb118
NSObject实例对象地址:0x100410520
NSObject 的类地址:0x7fff993fb118
NSObject 的元类地址:0x7fff993fb0f0
NSObject 父类的地址:(null):0x0
objMetaSuperClass 的元类地址:0x7fff993fb118
 ---------
Person实例的isa:0x100008138
Person类的isa:0x100008110
Person元类的isa:0x7fff993fb0f0
NSObject实例的isa:0x7fff993fb118
NSObject类的isa:0x7fff993fb0f0
NSObject元类的isa:0x7fff993fb0f0

开始分析:
Person 的父类是NSObject ,因为Person继承自NSObject,

Person 父类的地址:NSObject:0x7fff993fb118 和
NSObject 的类地址:0x7fff993fb118 地址是一样的
NSObject 父类的地址:(null):0x0 NSObject 父类是nil
Person的isa指向其元类 其元类的isa 指向NSObject的元类
NSObject的元类的isa 指向的是自己

WeChate55585c6ef593efe89bb041b256a26ed.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容