iOS Runtime 知识详解: http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/
一般可以运行Runtime进行以下操作:
1.在程序运行时,动态的添加一个类
2.在程序运行时,动态的修改一个类的属性,方法
3.遍历一个类的所有属性
举个🌰:
1.交换系统的方法和自定义的方法的实现.
如,使用NSString 的stringWithFormat可以得到一个字符串,如果想为这个字符串默认加上一段字符就可以使用runtime中的method_exchangeImplementations的实现.
如:写一个NSString的category.然后引入runtime,可以在load方法里面通过class_getClassMethod得到方法,然后通过method_exchangeImplementations交换即可.
NSString的category的代码如下:
NSString+str.m
// // NSString+str.m // Runtime // // Created by Shaoting Zhou on 2017/10/19. // Copyright © 2017年 Shaoting Zhou. All rights reserved. // #import "NSString+str.h" #import <objc/message.h> @implementation NSString (str) //当文件被加载进来时调用 +(void)load{ Method stringWithFormat = class_getClassMethod([NSString class], @selector(stringWithFormat:)); Method ST_stringWithFormat = class_getClassMethod([NSString class], @selector(ST_stringWithFormat:)); //方法交换 method_exchangeImplementations(stringWithFormat, ST_stringWithFormat); } +(instancetype)ST_stringWithFormat:(NSString *)str{ NSString * appendStr = [str stringByAppendingString:@",带上我"]; return appendStr; } @end
使用还是按照原来的stringWithFormat即可:
其中,苹果在iOS5.0之后,不建议使用底层代码,如果想要使用,需要修改配置,如
修改Build Setting中Enable strict ..........为NO即可.
2.动态添加方法
写一个继承于NSObject的类Person,然后调用一个它实现的方法.这个时候苹果为我们提供了一个方法:+(BOOL)resolveInstanceMethod:(SEL)sel可以在里面做一下处理.
这里介绍一下动态添加方法:class_addMethod
Person.m
// // Person.m // Runtime // // Created by Shaoting Zhou on 2017/10/19. // Copyright © 2017年 Shaoting Zhou. All rights reserved. // #import "Person.h" #import <objc/message.h> @implementation Person void runMe(){ NSLog(@"你没有实现这个方法"); } //当发现类有实例方法没有实现时,会提供一次机会做处理 +(BOOL)resolveInstanceMethod:(SEL)sel{ // NSLog(@"%@",NSStringFromSelector(sel)); //动态添加方法 if(sel == @selector(ppp)){ /* class 类 SEL 方法编号 IMP 方法实现 types 类型 */ class_addMethod([self class], sel, (IMP)runMe, ""); } return [super resolveInstanceMethod:sel]; } @end
3.获取属性
//动态的取属性 unsigned int count = 0; Ivar * ivars = class_copyIvarList([Person class], &count); // 遍历成员变量列表,其中每个变量都是Ivar类型的结构体 for (const Ivar *p = ivars; p < ivars + count; ++p) { Ivar const ivar = *p; // 获取变量名 NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)]; NSLog(@"%@",key); }
4.以后慢慢添加.