美文网首页
底层原理总结 — Category1

底层原理总结 — Category1

作者: 踩坑小分队 | 来源:发表于2020-02-08 21:26 被阅读0次

    Category的使用场景:
    为已有的类添加方法,扩展功能

    例:
    Person

    @interface Person : NSObject
    @end
    
    @implementation Person
    @end
    

    Person 的 Category

    #import "Person.h"
    
    @interface Person (Category1)<NSCoding>
    
    // 对象方法
    - (void)instanceMethod1;
    - (void)instanceMethod2;
    
    // 类方法
    + (void)classMethod1;
    + (void)classMethod2;
    @end
    
    @implementation Person (Category1)
    
    // 对象方法
    - (void)instanceMethod1 {
        NSLog(@"instanceMethod1");
    }
    - (void)instanceMethod2 {
        NSLog(@"instanceMethod2");
    }
    
    // 类方法
    + (void)classMethod1 {
        NSLog(@"classMethod1");
    }
    + (void)classMethod2 {
        NSLog(@"classMethod2");
    }
    @end
    

    我们来看一下Person+Category1编译的时候的底层结构吧
    clang 一下,生成.cpp文件

    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc Person+Category1.m -o PersonCategory.cpp
    

    Category存放在_category_t结构体中

    struct _category_t {
        const char *name;       // 类名
        struct _class_t *cls;
        const struct _method_list_t *instance_methods;  // 对象方法列表
        const struct _method_list_t *class_methods;     // 类方法列表
        const struct _protocol_list_t *protocols;       // 协议列表
        const struct _prop_list_t *properties;          // 属性列表
    };
    

    给结构体赋值

    static struct _category_t _OBJC_$_CATEGORY_Person_$_Category1 __attribute__ ((used, section ("__DATA,__objc_const"))) = 
    {
        "Person",   // 类名
        0, // &OBJC_CLASS_$_Person,
        (const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_Category1,// 对象方法列表
        (const struct _method_list_t *)&_OBJC_$_CATEGORY_CLASS_METHODS_Person_$_Category1, // 类方法列表
        (const struct _protocol_list_t *)&_OBJC_CATEGORY_PROTOCOLS_$_Person_$_Category1, // 协议列表
        0,  // 属性列表
    };
    

    我们分别看下这些列表对象:
    对象方法列表
    _OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_Category1

    static struct /*_method_list_t*/ {
        unsigned int entsize;  // sizeof(struct _objc_method)
        unsigned int method_count;
        struct _objc_method method_list[2];
    } _OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_Category1 __attribute__ ((used, section ("__DATA,__objc_const"))) = {
        sizeof(_objc_method),
        2,
        {{(struct objc_selector *)"instanceMethod1", "v16@0:8", (void *)_I_Person_Category1_instanceMethod1},
        {(struct objc_selector *)"instanceMethod2", "v16@0:8", (void *)_I_Person_Category1_instanceMethod2}}
    };
    
    image.png

    类方法列表:
    _OBJC_$_CATEGORY_CLASS_METHODS_Person_$_Category1

    static struct /*_method_list_t*/ {
        unsigned int entsize;  // sizeof(struct _objc_method)
        unsigned int method_count;
        struct _objc_method method_list[2];
    } _OBJC_$_CATEGORY_CLASS_METHODS_Person_$_Category1 __attribute__ ((used, section ("__DATA,__objc_const"))) = {
        sizeof(_objc_method),
        2,
        {{(struct objc_selector *)"classMethod1", "v16@0:8", (void *)_C_Person_Category1_classMethod1},
        {(struct objc_selector *)"classMethod2", "v16@0:8", (void *)_C_Person_Category1_classMethod2}}
    };
    
    image.png

    协议列表:
    _OBJC_CATEGORY_PROTOCOLS_$_Person_$_Category1

    struct _protocol_t _OBJC_PROTOCOL_NSCoding __attribute__ ((used)) = {
        0,
        "NSCoding",
        0,
        (const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_NSCoding,
        0,
        0,
        0,
        0,
        sizeof(_protocol_t),
        0,
        (const char **)&_OBJC_PROTOCOL_METHOD_TYPES_NSCoding
    };
    
    struct _protocol_t *_OBJC_LABEL_PROTOCOL_$_NSCoding = &_OBJC_PROTOCOL_NSCoding;
    
    static struct /*_protocol_list_t*/ {
        long protocol_count;  // Note, this is 32/64 bit
        struct _protocol_t *super_protocols[1];
    } _OBJC_CATEGORY_PROTOCOLS_$_Person_$_Category1 __attribute__ ((used, section ("__DATA,__objc_const"))) = {
        1,
        &_OBJC_PROTOCOL_NSCoding
    };
    
    image.png

    当然了也可以通过查看objc源码进行查看分类的实现
    下载源码:https://opensource.apple.com/tarballs/objc4/
    也能看到类似的结构

    image.png

    相关文章

      网友评论

          本文标题:底层原理总结 — Category1

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