结构模型

结构模型

  1. 介绍下runtime的内存模型(isa、对象、类、metaclass、结构体的存储信息等)
Class:
typedef struct objc_class *Class;

struct objc_class {

Class isa;  //指向meta_class

Class super_class;     //指向父类

const char* name;

long version;

long info;

long instance_size;

struct objc_ivar_list *ivars; //类的成员变量,使用数组存储,使用中基本不变化(只有动态生成的类才能添加成员变量Ivar),存取效率高。

struct objc_method_list **methodLists;  //类的成员方法,使用链表存储。使用中可能会增加方法,使用链表存储。

struct objc_cache *cache;   //类的方法缓存。

struct objc_protocol_list *protocols;  //类遵守的协议。   

};

对象
struct objc_object {

Class isa; //指向对象所属的类。

};

  1. 为什么要设计metaclass
    元类保存了类方法的列表
  1. class_copyIvarList & class_copyPropertyList区别
    class_copyPropertyList返回的仅仅是对象类的属性(@property申明的属性),而class_copyIvarList返回类的所有属性和变量(包括在@interface大括号中声明的变量)

  2. class_rw_t 和 class_ro_t 的区别
    ObjC 类中的属性、方法还有遵循的协议等信息都保存在 class_rw_t 中:其中还有一个指向常量的指针 ro,其中存储了当前类在编译期就已经确定的属性、方法以及遵循的协议。

  3. category如何被加载的,两个category的load方法的加载顺序,两个
    category的同名方法的加载顺序

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                       OBJC2_UNAVAILABLE;  // 父类
        const char *name                        OBJC2_UNAVAILABLE;  // 类名
        long version                                OBJC2_UNAVAILABLE;  // 类的版本信息,默认0
        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;

struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;    //存储实例方法
    struct method_list_t *classMethods;        //存储类方法
    struct protocol_list_t *protocols;            //协议
    struct property_list_t *instanceProperties;//属性
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;

    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) return classMethods;
        else return instanceMethods;
    }

    property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};

分类的实现原理是将category中的方法,属性,协议数据放在category_t结构体中,然后将结构体内的方法列表拷贝到类对象的方法列表中。

category的+load执行顺序是根据编译顺序决定的

  1. category & extension区别,能给NSObject添加Extension吗,结果如何
    Category的小括号中有名字,而Extension没有;
    Category只能扩充方法,不能扩充成员变量和属性;
    如果Category声明了声明了一个属性,那么Category只会生成这个属性的set,get方法的声明,也就不是会实现.
  1. 消息转发机制,消息转发机制和其他语言的消息机制优劣对比
    1.category
    2.运行时
    3.消息机制
    4.可以和C,C++,swift混和编程
    1.不支持命名空间
    2.不支持运算符重载
    3.不支持多重继承
    4.使用动态运行时类型,所有的方法都是函数点用,很多编译时的优化方法都用不到,如内联函数

  2. 在方法调用的时候,方法查询-> 动态解析-> 消息转发 之前做了什么
    1、正常判空处理
    2、TAGGED_POINTERS判断(后面文章再一起探究)
    3、通过isa指针拿到他的class(class中存储它的方法以及方法缓存)
    4、CacheLookup 查看方法缓存

  3. IMP、SEL、Method的区别和使用场景
    SEL
    SEL方法选择器,表示一个selector的指针
    无论什么类里,只要方法名相同,SEL就相同。项目里的所有SEL都保存在一个NSSet集合里(NSSet集合里的元素不能重复),所以查找对应方法,只要找到对应的SEL就可以了。
    SEL实际是根据方法名hash化了的字符串
    IMP
    定义:函数指针,指向方法实现的首地址。
    Method
    Method定义如下:它主要是用语描述类里面的方法

typedef struct objc_method *Method;
objc_method结构体定义如下

struct objc_method {
    SEL method_name                              OBJC2_UNAVAILABLE;//方法名
    char *method_types                           OBJC2_UNAVAILABLE;//参数返回值字符串描述
    IMP method_imp                               OBJC2_UNAVAILABLE;//方法的实现
}    
从上述代码可以看出,Method是一个结构体,包含了SEL和IMP成员变量。
实际上,相当于在SEL和IMP之间做了一个映射,有了Method,SEL就可以找到对应的IMP,从而调用方法。
  1. load、initialize方法的区别什么?在继承关系中他们有什么区别
    load和initialize会被自动调用,不能手动调用它们。
    子类实现了load和initialize的话,会隐式调用父类的load和initialize方法
    load和initialize方法内部使用了锁,因此它们是线程安全的。
    2.2 不同点
    子类中没有实现load方法的话,不会调用父类的load方法;而子类如果没有实现initialize方法的话,也会自动调用父类的initialize方法。
    load方法是在类被装在进来的时候就会调用,initialize在第一次给某个类发送消息时调用(比如实例化一个对象),并且只会调用一次,是懒加载模式,如果这个类一直没有使用,就不回调用到initialize方法。
    load
    父类先于子类调用
    类先于分类调用
    initialize 只会在对应类的方法第一次被调用时,如果一个子类没有实现 +initialize 方法,那么父类的实现是会被执行多次的,如果一个类的分类实现了 +initialize 方法,那么就会对这个类中的实现造成覆盖。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容