对象和类以前已经分析过了,今天来分析一下方法,说到方法就不得不探究一下Runtime了~c++
Runtime
是一套API。api
详细来讲,是一套由c、c++、汇编
一块儿编写而成,并为oc代码提供运行时功能的api。markdown
为何要这么费劲巴拉的搞这么一套东西,不直接用oc呢?app
运行时 & 编译时iphone
运行时:代码跑起来的时间,代码会被装载在内存ide
编译时:正在编译的时间,将源代码翻译成可识别的机器语言(如:二进制)函数
legacy version
, OC 1.0
,__OBJC__
,-old
modern version
, OC 2.0
,__OBJC2__
,-new
运行时动态库 Runtime System Library
经过 编译器 compiler
编译以后,提供了 Framework&Service
和 Runtime API
供OC使用。post
咱们常常在OC中调用@selector()
,其实就是在和runtime打交道了
@selector()
NSSelectorFromName
sel_registerName
测试代码:
// Person是继承自NSObject 自定义的类
Person *person = [Person alloc];
[person sayHello];
//定义一个void fly() {···},直接调用方法
fly();
复制代码
经过clang手段:
兼容编译(代码少):clang -rewrite-objc main.m -o main.cpp
完整编译(不报错):xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
复制代码
看一下底层编译成什么:
Person *person = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("sayHello"));
fly();
复制代码
解析:
((Person *(*)(id, SEL))(void *)objc_msgSend)
和 ((void (*)(id, SEL))(void *)objc_msgSend)
都是 类型强转(id)objc_getClass("Person")
拿到Person类sel_registerName("alloc")
和 sel_registerName("sayHello")
都是 调用方法,比如@selector()
fly()
在clang
后,并无编译成objc_msgSend
函数去调用。由于发送消息就是查找函数实现的过程,C函数能够直接经过函数名(指针)找到,并不须要这一步。重点即:objc_msgSend(id,sel)
= 发送消息(消息接收者,方法编号)
由底层编译能够看出,咱们调用方法,在底层会变成objc_msgSend
函数的调用。也就是说:
方法的本质就是发送消息
!
假定条件: 有一个子类 Person,实例方法:run ,类方法:jump 有一个父类 People,实例方法:sayHi,类方法:sayBey
//person的角度
objc_msgSend(person, sel_registerName("run"));
复制代码
//person的角度
objc_msgSend(objc_getClass("Person"), sel_registerName("jump"));
复制代码
给父类发消息,要用另外一个函数
objc_msgSendSuper
,而且要用到objc_super
这个结构体
struct objc_super {
//只看oc2版本须要的2个参数
__unsafe_unretained _Nonnull id receiver;
//···
__unsafe_unretained _Nonnull Class super_class;
//···
};
复制代码
//person 的角度
struct objc_super mySuper;
mySuper.receiver = person;
mySuper.super_class = [Person class];
objc_msgSendSuper(&mySuper, @selector(sayHi));
复制代码
//person 的角度
struct objc_super myClassSuper;
myClassSuper.receiver = [Person class];
myClassSuper.super_class = class_getSuperclass(object_getClass([Person class]));// 元类
objc_msgSendSuper(&myClassSuper, sel_registerName("sayBey"));
复制代码