Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。
这种特性意味着Objective-C不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。对于Objective-C来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行。这个运行时系统即Objc Runtime。Objc Runtime其实是一个Runtime库,它基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。
Runtime库主要做下面几件事:
- 封装:在这个库中,对象可以用C语言中的结构体表示,而方法可以用C函数来实现,另外再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,我们就可以在程序运行时创建,检查,修改类、对象和它们的方法了。
- 找出方法的最终执行代码:当程序执行[object doSomething]时,会向消息接收者(object)发送一条消息(doSomething),runtime会根据消息接收者是否能响应该消息而做出不同的反应。这将在后面详细介绍。
Objective-C runtime目前有两个版本:Modern runtime和Legacy runtime。Modern Runtime 覆盖了64位的Mac OS X Apps,还有 iOS Apps,Legacy Runtime 是早期用来给32位 Mac OS X Apps 用的,也就是可以不用管就是了。
在这一系列文章中,我们将介绍runtime的基本工作原理,以及如何利用它让我们的程序变得更加灵活。在本文中,我们先来介绍一下类与对象,这是面向对象的基础,我们看看在Runtime中,类是如何实现的。
以上是转载的内容,下面是我的总结
// runtime:运行时机制
/*
1.runtime是什么
1.1runtime是一套比较底层的C语言的API,属于一个C语言库,包含了很多C语言底层的API
1.2平时编写的OC代码,再程序运行过程中都转成了runtime的C语言代码
举例:[[Person alloc]init];
runtime:objc_msgSend(runtime:objc_msgSend("Person","alloc"),"init");
2.用过么,怎么用?
2.1runtime属于OC的底层,可以进行一些非常底层的操作(用OC无法实现,不好实现)
2.2再程序运行过程中,动态的创建一个类(比如KVO的底层实现,动态的创建一个被监听者的派生类)
2.3在程序运行过程中,动态地为某个类添加属性/方法,修改属性值/方法
2.4遍历一个类的所有成员变量、属性、方法、协议
3.相关的头文件<objc/runtime.h>,<objc/message.h>
// 4.相关应用
4.1 NSCoding归档和解档,利用runtime遍历模型对象的所有属性
4.2 字典->模型(利用runtime遍历模型对象的所有属性,根据属性名从字典中取出对应的值,设置到模型上的属性上)
4.3 KVO--利用runtime动态产生一个类
4.4 用于封装框架(想怎么改,怎么改)
// 5.相关函数
5.1 objc_msgSend:給对象发送消息
5.2 class_copyMethodList :遍历某个类的所有的方法
5.3 class_copyIvarList :遍历某个类的所有成员变量
5.4 class_copyProtocolList 遍历某个类的所有协议
*/
----获取一个类的成员变量
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 获取一个类的成员变量
unsigned int count =0;
Ivar *ivars =class_copyIvarList([Person class], &count);
for (int i = 0; i < count; ++i) {
Ivar ivar = ivars[i];
const char *cName = ivar_getName(ivar);
NSString *OCName = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
NSLog(@"ivar:%@",OCName);
}
2016-05-21 13:16:57.727 runtime使用复习[14352:915485] ivar:_height
2016-05-21 13:16:57.727 runtime使用复习[14352:915485] ivar:_name
2016-05-21 13:16:57.727 runtime使用复习[14352:915485] ivar:_age
----获取一个类的所有方法
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取一个类的所有方法
unsigned int count =0;
Method *methods = class_copyMethodList([Person class], &count);
for (int i = 0; i < count; ++i) {
Method method = methods[i];
//* @note To get the method name as a C string, call \c sel_getName(method_getName(method)).
SEL sel = method_getName(method);
// 获取C语言方法
const char *selMethod = sel_getName(sel);
NSString *OCSel = [NSString stringWithCString:selMethod encoding:NSUTF8StringEncoding];
NSLog(@"%@",OCSel);
}
}
2016-05-21 13:20:16.843 runtime使用复习[14364:918597] age
2016-05-21 13:20:16.844 runtime使用复习[14364:918597] setAge:
2016-05-21 13:20:16.844 runtime使用复习[14364:918597] .cxx_destruct
2016-05-21 13:20:16.844 runtime使用复习[14364:918597] name
2016-05-21 13:20:16.844 runtime使用复习[14364:918597] setName:
2016-05-21 13:20:16.844 runtime使用复习[14364:918597] encodeWithCoder:
2016-05-21 13:20:16.845 runtime使用复习[14364:918597] initWithCoder:
2016-05-21 13:20:16.845 runtime使用复习[14364:918597] height
2016-05-21 13:20:16.845 runtime使用复习[14364:918597] setHeight:
----对于一个类属性比较多药归档时使用runtime归档,可以减少代码量
-(void)encodeWithCoder:(NSCoder *)aCoder{
unsigned int count =0;
Ivar *ivars =class_copyIvarList([Person class], &count);
for (int i = 0; i < count; ++i) {
Ivar ivar = ivars[i];
const char *cName = ivar_getName(ivar);
NSString *key = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
// NSLog(@"ivar:%@",OCName);
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
free(ivars);
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self =[super init]) {
unsigned int count =0;
Ivar *ivars =class_copyIvarList([Person class], &count);
for (int i = 0; i < count; ++i) {
Ivar ivar = ivars[i];
const char *cName = ivar_getName(ivar);
NSString *key = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
id value =[aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
free(ivars);
}
return self;
}