美文网首页
iOS-Category

iOS-Category

作者: e297b14c9e53 | 来源:发表于2020-03-13 02:39 被阅读0次

    面试题

    Category的使用场合是什么?
    Category的实现原理
    • Category编译之后的底层结构是struct category_t,里面存储着分类的对象方法、类方法、属性、协议信息
    • 在程序运行的时候,runtime会将Category的数据,合并到类信息中(类对象、元类对象中)
    Category和Class Extension的区别是什么?
    • Class Extension在编译的时候,它的数据就已经包含在类信息中
    • Category是在运行时,才会将数据合并到类信息中
    Category中有load方法吗?load方法是什么时候调用的?load 方法能继承吗?
    • 有load方法
    • load方法在runtime加载类、分类的时候调用
    • load方法可以继承,但是一般情况下不会主动去调用load方法,都是让系统自动调用
    load、initialize方法的区别什么?它们在category中的调用的顺序?以及出现继承时他们之间的调用过程?
    • 区别是什么?
      1.调用方式
      1> load是根据函数地址直接调用
      2> initialize是通过objc_msgSend调用
      2.调用时刻
      1> load是runtime加载类、分类的时候调用(只会调用1次)
      2> initialize是类第一次接收到消息的时候调用,每一个类只会initialize一次(父类的initialize方法可能会被调用多次)

    • load、initialize的调用顺序?

      • load
        1> 先调用类的load
        a) 先编译的类,优先调用load
        b) 调用子类的load之前,会先调用父类的load
        2> 再调用分类的load
        a) 先编译的分类,优先调用load
      • initialize
        1> 先初始化父类
        2> 再初始化子类(可能最终调用的是父类的initialize方法)
    Category能否添加成员变量?如果可以,如何给Category添加成员变量?
    • 不能直接给Category添加成员变量,但是可以间接实现Category有成员变量的效果

    Category

    Category的底层结构
    • 定义在objc-runtime-new.h中


    Category的加载处理过程
    • 通过Runtime加载某个类的所有Category数据
    • 把所有Category的方法、属性、协议数据,合并到一个大数组中,后面参与编译的Category数据,会在数组的前面
    • 将合并后的分类数据(方法、属性、协议),插入到类原来数据的前面
    源码解读顺序
    • objc-os.mm
      • _objc_init
      • map_images
      • map_images_nolock
    • objc-runtime-new.mm
      • _read_images
      • remethodizeClass
      • attachCategories
      • attachLists
      • realloc、memmove、 memcpy
    +load方法
    • +load方法会在runtime加载类、分类时调用
    • 每个类、分类的+load,在程序运行过程中只调用一次
    • 调用顺序
      • 先调用类的+load
        • 按照编译先后顺序调用(先编译,先调用)
        • 调用子类的+load之前会先调用父类的+load
    • 再调用分类的+load
      • 按照编译先后顺序调用(先编译,先调用)
    • objc4源码解读过程:objc-os.mm
      • _objc_init
      • load_images
      • prepare_load_methods
        • schedule_class_load
        • add_class_to_loadable_list
        • add_category_to_loadable_list
      • call_load_methods
        • call_class_loads
        • call_category_loads
        • (*load_method)(cls, SEL_load)
    • +load方法是根据方法地址直接调用,并不是经过objc_msgSend函数调用
    +initialize方法
    • +initialize方法会在类第一次接收到消息时调用
    • 调用顺序
      • 先调用父类的+initialize,再调用子类的+initialize
      • (先初始化父类,再初始化子类,每个类只会初始化1次)
    • +initialize和+load的很大区别是,+initialize是通过objc_msgSend进行调用的,所以有以下特点
      • 如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)
      • 如果分类实现了+initialize,就覆盖类本身的+initialize调用
    • objc4源码解读过程
      • objc-msg-arm64.s
        • objc_msgSend
      • objc-runtime-new.mm
        • class_getInstanceMethod
        • lookUpImpOrNil
        • lookUpImpOrForward
        • _class_initialize
        • callInitialize
        • objc_msgSend(cls, SEL_initialize)
    如何实现给分类“添加成员变量”?
    • 默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。但可以通过关联对象来间接实现
    • 关联对象提供了以下API
      • 添加关联对象
      void objc_setAssociatedObject(id object, const void * key,
                                    id value, objc_AssociationPolicy policy)
      
      • 获得关联对象
        id objc_getAssociatedObject(id object, const void * key) 
      
      • 移除所有的关联对象
        void objc_removeAssociatedObjects(id object)
      
      • key的常见用法
        static void *MyKey = &MyKey;
        objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        objc_getAssociatedObject(obj, MyKey)
      
        static char MyKey;
        objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        objc_getAssociatedObject(obj, &MyKey)
      
        // 使用属性名作为key
        objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        objc_getAssociatedObject(obj, @"property");
        // 使用get方法的@selecor作为key
        objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        objc_getAssociatedObject(obj, @selector(getter))
      
    • objc_AssociationPolicy
    • 关联对象的原理
      • 实现关联对象技术的核心对象有AssociationsManagerAssociationsHashMapObjectAssociationMapObjcAssociation
      • objc4源码解读:objc-references.mm




    相关文章

      网友评论

          本文标题:iOS-Category

          本文链接:https://www.haomeiwen.com/subject/dqxojhtx.html