美文网首页
底层原理总结 — 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