正文
###一:基础概念
RunTime简称运行时,就是系统在运行的时候的一些机制,其中最主要的是消息机制。
对于C语言,函数的调用在编译的时候会决定调用哪个函数,编译完成之后直接顺序执行,无任何二义性。
OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。
只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用。
Objective-C 从三种不同的层级上与 Runtime 系统进行交互,分别是:
1、通过 Objective-C 源代码;
2、通过 Foundation 框架的NSObject类定义的方法;
3、通过对 runtime 函数的直接调用。
大部分情况下你就只管写你的Objc代码就行,runtime 系统自动在幕后辛勤劳作着。
###二:runtime的具体实现
我们写的oc代码,它在运行的时候也是转换成了runtime方式运行的,更好的理解runtime,也能帮我们更深的掌握oc语言。每一个oc的方法,底层必然有一个与之对应的runtime方法。
当我们用OC写下这样一段代码
[tableView cellForRowAtIndexPath:indexPath];
在编译时RunTime会将上述代码转化成[发送消息]
objc_msgSend(tableView, @selector(cellForRowAtIndexPath:),indexPath);
###三:常见方法
#####1、获取属性列表
//People.h
@interface People : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSUInteger age;
@end
//People.m
@interface People() {
NSString *aaa;
}
@property (nonatomic, strong) NSString *fatherName;
@end
@implementation People {
NSString *bbb;
}
@end
//获取所有属性
-(void)getAllProperty {
unsigned int count = 0;
objc_property_t *propertyList = class_copyPropertyList([People class], &count);
for (unsigned int i=0; i<count; i++) {
const char *propertyName = property_getName(propertyList[i]);
NSLog(@"property---->%@", [NSString stringWithUTF8String:propertyName]);
}
}
打印结果:
结论:
1)、不管是在.h文件中定义的属性还是在.m文件中定义的属性,都可以通过获取属性列表方法来进行获取;
2)、成员变量不同于属性,不能通过该方法来获取;
3)、先输出的是.m文件中的属性,然后才是.h文件中的属性,并且是按照属性定义的先后顺序来保存。
#####2、获取方法列表
//People.h
@interface People : NSObject
@property (nonatomic, strong) NSString *name;
-(void)iPrintName;
+(void)cPrintName;
@end
//People.m
@interface People() {
NSString *aaa;
}
@property (nonatomic, strong) NSString *fatherName;
@end
@implementation People {
NSString *bbb;
}
//-(void)printName {
//
//}
+(void)cPrintName {
}
-(void)printAge {
}
@end
//获取方法(不包括类方法)列表
-(void)getAllMethod {
unsigned int count = 0;
Method *methodList = class_copyMethodList([People class], &count);
for (unsigned int i=0; i<count; i++) {
Method method = methodList[i];
NSLog(@"method---->%@", NSStringFromSelector(method_getName(method)));
}
}
结论:
1)、类方法不能通过这个函数去获取到;
2)、只有在.m文件中实现了的方法才能被获取到,在.h文件中定义了,但是.m中没有实现的并不能获取到;
3)、对于使用@property定义的属性,会自动生成setter和getter方法,同样能被这个方法获取到;
4)、.m实现中还隐藏了一个.cxx_destruct也就是oc中常见delloc方法;
5)、保存顺序是优先保存用户在.m文件中实现的,其次是.m属性自动生成的getter和setter方法,然后是隐藏的delloc方法,最后是.h属性自动生成的getter和setter方法。
#####3、获取成员变量列表
//People.h
@interface People : NSObject {
NSString *cccc;
}
@property (nonatomic, strong) NSString *name;
@end
//People.m
@interface People() {
NSString *aaa;
}
@property (nonatomic, strong) NSString *fatherName;
@end
@implementation People {
NSString *bbb;
}
@end
-(void)getAllIvar{
unsigned int count = 0;
Ivar *ivarList = class_copyIvarList([People class], &count);
for (unsigned int i=0; i<count; i++) {
Ivar myIvar = ivarList[i];
const char *ivarName = ivar_getName(myIvar);
NSLog(@"Ivar---->%@", [NSString stringWithUTF8String:ivarName]);
}
}
打印结果:
结论:
1)、成员变量的保存是从.h文件开始,然后才是.m文件中的成员变量;
2)、用@property 定义的属性,会自动生成以_开头的成员变量,也是先保存.h文件生成的,再保存.m文件生成的。
#####4、获取协议列表
//People.h
@protocol PeopleDelegate <NSObject>
-(void)people;
@end
@interface People : NSObject
@property (nonatomic, strong) NSString *name;
//@property (nonatomic, weak) id <PeopleDelegate> delegate;
@end
//People.m
@interface People()
@property (nonatomic, strong) NSString *fatherName;
@end
@implementation People
@end
//ViewController.m
@interface ViewController ()<PeopleDelegate,UITabBarDelegate,UITableViewDataSource>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self getProtocal];
}
@end
//获取协议列表
-(void)getProtocal {
unsigned int count = 0;
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count); //这里变成了self
for (unsigned int i = 0; i<count; i++) {
Protocol *myProtocal = protocolList[i];
const char *protocolName = protocol_getName(myProtocal);
NSLog(@"protocol---->%@", [NSString stringWithUTF8String:protocolName]);
}
}
打印结果:
结论:
1)、只要声明遵循该协议,在引用的时候,就能获取到该类包含的协议列表,哪怕你没有指定代理的对象,也没有去实现协议的方法