- Runtime是运行时机制,是一套纯C的代码库,是OC的幕后工作者,整个OC的底层,我们编写的OC代码,在程序运行的时候,都经过Runtime机制转译成了C语言代码。
- Runtime是运行时机制,其中最主要的是消息机制。
- 对于C语言而言,函数的调用在编译的时候决定调用哪个函数。
- 而对于OC而言,并不会在编译的时候真正决定调用哪个函数,只有在真正调用的时候,才会根据函数的名称找到对应的函数来调用。
- 在编译阶段,OC可以调用任何已声明的函数,至于函数是否实现,并不重要。
- 在编译阶段,C调用未实现的函数,将会报错。
验证Runtime的消息发送机制
- 修改Xcode配置,在如图所示位置,将原来的YES修改为NO
- 验证消息发送机制代码如下:
// 1、创建一个集成自NSObject的类,并声明一些方法,实现这些方法
// Person.h
@interface Person : NSObject
- (void)sayHello;
- (void)sayMessage:(NSString *)message;
- (void)sayMessage:(NSString *)message WithBool:(BOOL)isBool;
@end
// Person.m
@implementation Person
- (void)sayHello{
NSLog(@"Hello");
}
- (void)sayMessage:(NSString *)message{
NSLog(@"%@",message);
}
- (void)sayMessage:(NSString *)message WithBool:(BOOL)isBool{
if (isBool) {
NSLog(@"%@",message);
}
}
@end
// 2、验证消息发送机制代码如下:
// ViewController.m
#import <objc/message.h> // 需要导入此框架,验证消息发送机制
#import "Person.h"
// 验证代码示例如下:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"----验证消息发送机制-开始----");
// OC调用示例:
[self exampleTransferWithOC];
// 该行代码经过runtime就编译成了objc_msgSend(self,@selector(exampleTransferWithOC)); 向self发送exampleTransferWithOC方法
// 消息发送机制示例:
objc_msgSend(self, @selector(exampleTransferWithOC));
NSLog(@"------分隔线--------");
[self exampleTransferWithmsgSend];
objc_msgSend(self, @selector(exampleTransferWithmsgSend));
NSLog(@"------分隔线--------");
// 验证
[self otherTest];
NSLog(@"----验证消息发送机制-结束----");
}
- (void)exampleTransferWithOC{
Person *per = [[Person alloc]init];
[per sayHello];
[per sayMessage:@"说句话听听"];
}
- (void)exampleTransferWithmsgSend{
id object = objc_msgSend([Person class], @selector(alloc));
Person *per = objc_msgSend(object, @selector(init));
objc_msgSend(per,@selector(sayHello));
objc_msgSend(per, @selector(sayMessage:),@"我也会说hello");
// 多个参数方法的消息发送
objc_msgSend(per, @selector(sayMessage:WithBool:),@"我要说话",NO);
}
- (void)otherTest{
Person *per = objc_msgSend(objc_msgSend(objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init"));
objc_msgSend(per,sel_registerName("sayHello"));
/*
objc_getClass("Person")表示获得类对象,等同于[Person class]
sel_registerName("alloc")表示注册一个方法,等同于@selector(alloc)
*/
}
@end
Runtime的作用
Runtime的作用:
1. 动态添加方法(KVO中,监听数组)
2. 动态生成类(KVO机制中,系统动态为我们生成了一个中间类,帮助我们完成观察者对象和被观察对象数据的传递)
3. 动态获取每个类中的属性名和实例变量名
总结:
runtime
验证必须导入头文件<objc/message.h>
- 任何方法的调用,其本质就是消息的发送;利用
runtime
进行消息的发送,Objective-C的底层实现就是利用runtime
实现的。 - 验证消息发送机制时,需要更改Xcode配置,查找build setting -> 搜索msg,设置为NO。
- 验证消息发送机制时,主要是利用方法
id objc_msgSend(id self, SEL op, ...)
,参数id self
是指消息的接受者,也是方法的执行者,例如上述的对象per;参数SEL op
是指发送的消息,也就是方法执行者将要执行的方法;后续的参数是发送消息的附带参数,也就是指方法的参数;返回值是一个泛指类型。 - 利用
runtime
消息发送机制,可以调用系统API中或是框架中的私有方法。 - 方法列表的位置:如果是对象方法,位于类对象的方法列表;如果是类方法,则位于元类中的方法列表。
runtime
消息发送机制,方法调用过程。
- 例如如何去调用对象方法sayHello:通过isa指针去对应的类中查找 -> 注册方法编号 -> 根据方法编号去查找对应方法(找到只是最终函数实现地址,根据地址去方法区调用对应函数)
- 总的来说:一个对象被初始化后,内部会有一个isa指针,指向类对象(类对象的方法列表),类对象中会有一个方法列表,此时会根据方法列表注册方法编号,方法编号对应方法列表,根据方法编号查找对应的方法,找到的只是最终函数的实现地址,根据地址去内存中的方法区调用对应函数