今天,我们来说说运行时的最常见的三种用法,在之前的一篇博客中,已经介绍了使用运行时给分类添加属性,详见:运行时给分类添加属性
前提条件,必须导入相关的头文件:
#import <objc/runtime.h>
那么剩下的两个用法:
动态获取某个类的所有属性
- 首先创建一个person类,设置两个属性,看能否获取的到我们的这两个属性:
ZYPerson.h
@interface ZYPerson : NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)int age;
+ (instancetype)personWithDict:(NSDictionary *)dict;
+ (NSArray *)properties;
- 我们接下来在.m文件中实现以下:‘
#import <objc/runtime.h>
@implementation ZYPerson
+ (instancetype)personWithDict:(NSDictionary *)dict
{
id obj = [[self alloc]init];
[obj setValuesForKeysWithDictionary:dict];
return obj;
}
+(NSArray *)properties
{
NSMutableArray *pros = [NSMutableArray array];
//属性个数
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (NSInteger index = 0 ; index < count ; index ++)
{
//根据index获得对应的属性
objc_property_t proerty = properties[index];
//获得属性的名字
const char *pname = property_getName(proerty);
//转成OC字符串
NSString *name = [[NSString alloc]initWithCString:pname encoding:NSUTF8StringEncoding];
[pros addObject:name];
}
return pros;
}
- 我们在viewDidLoad中调用一下,看能否打印出我们所需的内容
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",[ZYPerson properties]) ;
}
结果如下:还是比较给力的。对吧
交换两个方法的实现
- 接下来,我们看一下如何使用运行时来交换两个方法的实现:
- 我们还是在viewController中写代码:
+ (void)load
{
//交互方法的实现
//当系统调用viewDidLoad时,调用自定义的myViewDidLoad
//当系统调用myViewDidLoad时,调用自定义的viewDidLoad
method_exchangeImplementations(class_getInstanceMethod([self class], @selector(viewDidLoad)), class_getInstanceMethod([self class], @selector(myViewDidLoad)));
}
然后我们在myViewDidLoad中:
- (void)myViewDidLoad
{
NSLog(@"myViewDidLoad");
}
在viewDidLoad中:
- (void)viewDidLoad {
[super viewDidLoad];
}
看一下运行的结果:
过程是这样的,当程序启动的时候,先运行viewDidLoad方法,但是由于我们的laod方法中实现了两个方法的交换,所以他右马上调用了我们的myViewDidLoad方法