更多文章请点击下方:
引言
我们知道Objective-C提供的运行时,对于同一个函数,放在c语言中如果没有实现这个函数,编译是会报错的,但对于OC仅仅声明此方法,并未实现,编译是不会报错的,但只有程序运行后才会报错。 其实,我们runtime底层会提供很多方法。
接下来我们先阐述一下oc对象
对象
我们代码编写创建一个对象,通过Clang命令来进行编译生成.cpp文件
clang -rewrite-objc xxx.m -o xxx.cpp
查看该文件,会发现创建对象的该类的定义
typedef struct objc_object CuctomClass;
如代码所示,对象的本质是一个结构体。
方法
对象初始化代码如下:
CuctomClass *p = ((CuctomClass *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("CuctomClass"), sel_registerName("new"));
如代码所示,方法的本质就是发送消息,接下来我们通过对象发送一个消息。
每个消息都会调用objc_msgsend
((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("run"));
第一对象是Objc强制转换,代表消息接收者(void (*)(id, SEL))(void *)objc_msgSend)((id)p 第二参数代码方法编号sel_registerName("run") 其实是一个字符串
方法调用的过程其实就是通过方法编号SEL找到底层对应的IMP(函数实现的指针)。
Runtime 调用的方式
- Runtime 提供的API,请参考:Runtime API
- NSObject 提供的API,如:isKindOf、isMemberOf
- 编译器提供Oc上层方法,如:@seletor
类方法
类方法的调用,如下代码:
id cls = [CustomeClass class];
void *pointA = &cls;
[(__bridge id)pointA run];
objc_msgSend(objc_getclass("CustomeClass"), sel_registerName("run"));
类方法存在元类,对象方法存在类,类存在元类,都是以实例方法形式存在的
有一幅经典isa走位图: