Runtime底层解析 - 方法:method_t

method_t
Runtime底层解析 - 方法:method_t_第1张图片
method_t是对方法\函数的封装
struct method_t {
    SEL name; //函数名
    const char *types; //编码(返回值类型、参数类型)
    IMP imp;//指向函数的指针(函数地址)
};
  • 断点查看方法
  1. 仿源码自定义ClassInfo.h,从源码中抽出Class结构
struct class_rw_t {
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro;
    method_list_t * methods;    // 方法列表
    property_list_t *properties;    // 属性列表
    const protocol_list_t * protocols;  // 协议列表
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
};

/* OC对象 */
struct objc_object {
    void *isa;
};

/* 类对象 */
struct objc_class : objc_object {
    Class superclass;
    cache_t cache;
    class_data_bits_t bits;
public:
    class_rw_t* data() {
        return bits.data();
    }
    
    objc_class* metaClass() {
        return (objc_class *)((long long)isa & ISA_MASK);
    }
};
  1. 断点查看:
  objc_class *cls = (__bridge objc_class *)[Person class];
  class_rw_t *data = cls->data();
   [person age:10 height:20];
  • SEL代表方法\函数名,一般叫做选择器,底层结构跟char *类似(@selector(test) 类似于 "test"):
  1. 可以通过@selector()sel_registerName()获得;
  2. 可以通过sel_getName()NSStringFromSelector()转成字符串;
  3. 不同类中相同名字的方法,所对应的方法选择器是相同的。
  • IMP代表函数的具体实现:
  1. 本质就是一个"*".
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
  • types包含了函数返回值、参数编码的字符串
//举例:
// type ==  "i 24 @ 0 : 8 i 16 f 20"
// "i"     : 返回值类型"int";
//"24"  : 所有参数占的字节数;
//"@"   : 第一个参数,"id"类型;指针,8个字节;
//":"     :第二个参数: "SEL"; 指针,8个字节;
//"i"      : 第三个参数,"int";4
// "f"    : 第四个参数, "float";4
// "0"、"8"、"16"、"20" : 参数从多少字节开始
- (int)age:(int)age height:(float)height;

没有参数的OC函数,实际的样式:
- (void) test {
}
||
||
- (void) test :(id)self _cmd:(SEL)_cmd {
}

你可能感兴趣的:(Runtime底层解析 - 方法:method_t)