专栏名称: Adrenine
iOS开发
目录
相关文章推荐
51好读  ›  专栏  ›  Adrenine

iOS开发笔记之Runtime

Adrenine  · 掘金  ·  · 2017-12-13 08:46

正文

###一:基础概念 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方法。

image

当我们用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)、只要声明遵循该协议,在引用的时候,就能获取到该类包含的协议列表,哪怕你没有指定代理的对象,也没有去实现协议的方法







请到「今天看啥」查看全文