method_t
method_t是对方法\函数的封装
struct method_t {
SEL name; //函数名
const char *types; //编码(返回值类型、参数类型)
IMP imp;//指向函数的指针(函数地址)
};
- 仿源码自定义
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);
}
};
- 断点查看:
objc_class *cls = (__bridge objc_class *)[Person class];
class_rw_t *data = cls->data();
[person age:10 height:20];
-
SEL
代表方法\函数名,一般叫做选择器,底层结构跟char *
类似(@selector(test)
类似于 "test"
):
- 可以通过
@selector()
和sel_registerName()
获得;
- 可以通过
sel_getName()
和NSStringFromSelector()
转成字符串;
- 不同类中相同名字的方法,所对应的方法选择器是相同的。
- 本质就是一个"
*
".
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...);
//举例:
// 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 {
}
网友评论