runtime的功能很强大,包含的的内容也很多,见下图
但是我们平时项目中使用的并不是很多,以下是几种常见的场景:
1. 字典转换为模型。
通过网络接口获取的数据一般是 JSON 格式的,需要转为我们自定义的模型,方便使用。
定义BaseModel,所有模型的基类。
BaseModel.h
#import <Foundation/Foundation.h>
@interface BaseModel : NSObject
-(id)initWithDic:(NSDictionary *)dic;
@end
BaseModel.m
#import "BaseModel.h"
#import <objc/runtime.h>
@implementation BaseModel
-(id)initWithDic:(NSDictionary *)dic{
//Class cls = [self class];
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i=0; i<count; i++) {
objc_property_t property = properties[i];
NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
id value = [dic objectForKey:propertyName];
if (!value) {
continue;
}
[self setValue:value forKey:propertyName];
}
free(properties);
return self;
}
@end
定义数据模型Model
Model.h
#import "BaseModel.h"
@interface Model : BaseModel
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *sex;
@property (nonatomic, strong) NSNumber *age;
@end
Model.m
#import "Model.h"
@implementation Model
@end
声明Model的实例并使用
NSDictionary *dic = @{@"name": @"Brook",
@"sex": @"male",
@"age": @(10)};
Model *model = [[Model alloc] initWithDic:dic];
NSLog(@"model name=%@", model.name);
2.Method Swizzling
在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写、和借助类别重名方法暴力抢先之外,还有一个方法就是Method Swizzling.
Person.m
#import "Person.h"
#import <objc/runtime.h>
@implementation Person
-(NSString *)run{
return @"run";
}
-(NSString *)study{
return @"study";
}
@end
Person.h
#import "Animal.h"
@interface Person : Animal
-(NSString *)run;
-(NSString *)study;
@end
上面是一般情况,调用结果如下:
添加Method Swizzling魔法,修改Person.m代码
#import "Person.h"
#import <objc/runtime.h>
@implementation Person
+(void)load1{
Method methodRun = class_getInstanceMethod([self class], @selector(run));
Method methodStudy = class_getInstanceMethod([self class], @selector(study));
method_exchangeImplementations(methodRun, methodStudy);
}
-(NSString *)run{
return @"run";
}
-(NSString *)study{
return @"study";
}
@end
添加魔法后的调用结果:
两个方法进行了调用,著名下拉刷新第三方软件MJRefresh中使用过这个。