先上一张图,了解一下,runtime对于我们开发而言可以用到哪些地方(借用网络大神的)
1.先了解一下,运用runtime实现访问对象的成员变量,这里以一个字典转模型说明:
person.h 文件,声明了若干个成员变量
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (assign,nonatomic) int ID;
@property (assign,nonatomic) int weight;
@property (assign,nonatomic) int age;
@property (copy,nonatomic) NSString *name;
@property (assign,nonatomic) int gradeID;
- (void)eat;
- (void)run;
@end
NSObject+JSON.m 文件
(1)ivar_getTypeEncoding(ivar) 获取成员变量类型
(2)ivar_getName(ivar) 获取成员变量名
#import "NSObject+JSON.h"
#import <objc/runtime.h>
@implementation NSObject (JSON)
+ (instancetype)objectWithJson:(NSDictionary *)json {
id obj = [[self alloc]init];
unsigned int count;
Ivar *ivars = class_copyIvarList(self, &count);
for (int i=0; i<count; i++) {
// 取出成员变量
Ivar ivar = ivars[I];
NSMutableString *type = [NSMutableString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
NSMutableString *name = [NSMutableString stringWithUTF8String:ivar_getName(ivar)];
NSLog(@"type=%@,name=%@",type,name);
[name deleteCharactersInRange:NSMakeRange(0, 1)];
// 设值
id value = json[name];
if (value) {
if ([name isEqualToString:@"ID"]) {
value = json[@"id"];
}
[obj setValue:value forKey:name];
}else {
// 这里是做了特殊处理,设置了默认值,正常是不需要的
if ([type isEqualToString:@"i"]) {
[obj setValue:@0 forKey:name];// int 类型,默认值
} else {
[obj setValue:@"" forKey:name]; // NSString 类型,默认值
}
}
}
free(ivars);
return obj;
}
@end
// 字典转模型
- (void)jsonToModel {
NSDictionary *json = @{
@"id":@20,
@"age":@20,
// @"weight":@60,
@"name":@"jack",
@"num":@123
};
Person *person = [Person objectWithJson:json];
NSLog(@"%@",person);
NSLog(@"id = %d, age = %d, weight = %d, name = %@",person.ID,person.age,person.weight,person.name);
}
如果字典中没有给出对应的成员变量,则使用的默认值处理方法
2.还有一个关于runtime,实现方法交换的例子,在person.h里有eat(),run()方法,如果要实现两个方法的交换,两种方法:
方法一:
class_replaceMethod([Person class], @selector(run), imp_implementationWithBlock(^{
NSLog(@"我是替换的方法");
}), "V");
方法二:
Method run = class_getInstanceMethod([Person class], @selector(run));
Method eat = class_getInstanceMethod([Person class], @selector(eat));
method_exchangeImplementations(run, eat);
如果需要交换外部方法,还可以有方法三:
// 替换的方法
void myRun() {
NSLog(@"---myRun---");
}
- (void)exchangeMethod {
Person *person = [[Person alloc]init];
//方法一:
// class_replaceMethod([Person class], @selector(run), imp_implementationWithBlock(^{
// NSLog(@"我是替换的方法");
// }), "V");
//方法二:
// Method run = class_getInstanceMethod([Person class], @selector(run));
// Method eat = class_getInstanceMethod([Person class], @selector(eat));
// method_exchangeImplementations(run, eat);
//方法三:
class_replaceMethod([Person class], @selector(run), (IMP)myRun, "V");
[person run];
}