RunTime的理解
runtime:运行时刻是指一个程序在运行(或者在被执行)的状态。也就是说,当你打开一个程序使它在电脑上运行的时候,那个程序就是处于运行时刻。在一些编程语言中,把某些可以重用的程序或者实例打包或者重建成为“运行库"。这些实例可以在它们运行的时候被连接或者被任何程序调用。
OC中runtime:是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。 在我们平时编写的OC代码, 在程序运行过程时, 都会转换成runtime的C语言代码。比如类转成了runtime库里面的结构体等数据类型,方法转成了runtime库里面的C语言函数,平时调方法都是转成了objc_msgSend函数(所以说OC有个消息发送机制)
RunTime学习路线
RunTime的实际使用
要我说RunTime对于初学者或者刚入门者就是装逼用的,啥用没有,
runtime最常用的几个用法:
动态的为一个类添加/修改/删除 成员变量、方法
而这些很少在平常的Coding中运用上,所以我说中级以下开发者,拿这些装B就行了。
import : 成员变量、类、方法
class_copyIvarList : 获得某个类内部的所有成员变量
class_copyMethodList : 获得某个类内部的所有方法
class_getInstanceMethod : 获得某个具体的实例方法(对象方法,减号开头)
class_getClassMethod : 获得某个具体的类方法 (加号)
method_exchangeImplementations : 交换2个方法的实现
1.objc_setAssociatedObject(self, &FYObjProKey, hotelName, OBJC_ASSOCIATION_COPY);
self 是要给哪个对象添加 变量
&FYObjProKey 是对这个变量的标记,获得这个变量也是需要这个key值得
hotelName 是 这个 变量的值
OBJC_ASSOCIATION_COPY 这个 是添加变量的策略,和属性的copy类似
一共有 5 个策略
OBJC_ASSOCIATION_ASSIGN; //assign策略
OBJC_ASSOCIATION_COPY_NONATOMIC; //copy,nonatomic策略
OBJC_ASSOCIATION_RETAIN_NONATOMIC; // retain,nonatomic策略
OBJC_ASSOCIATION_RETAIN //retain策略
OBJC_ASSOCIATION_COPY //copy策略
2.objc_getAssociatedObject(self, &FYObjProKey)
通过 &FYObjProKey 这个标记 获得 新添加的变量
代码示例
先定义一个Car类
///.h文件
#import <Foundation/Foundation.h>
@interface Car : NSObject
@property (nonatomic, copy)NSString *name;
- (void)runRun;
- (void)stopStop;
- (void)guess;
@end
///.m文件
#import "Car.h"
@implementation Car
- (void)runRun
{
NSLog(@"法拉利,跑跑跑");
}
- (void)stopStop
{
NSLog(@"劳斯莱,停停停");
}
@end
在写Car类的分类
#import "Car.h"
#import <objc/runtime.h>
@interface Car (RunTime)
@property(nonatomic,copy) NSString *allTime;
@end
#import "Car+RunTime.h"
static NSString *key = @"key";///这里只是一个Key标示
@implementation Car (RunTime)
////动态为Category扩展加属性
////动态的为扩展添加实现方法
- (void)setAllTime:(NSString *)allTime
{
objc_setAssociatedObject(self, &key, allTime, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(NSString *)allTime
{
return objc_getAssociatedObject(self,&key);
}
@end
使用方法
#import "ViewController.h"
#import <objc/runtime.h>
#import "Car+RunTime.h"
/*
能动态为一个类添加/修改/删除 一个成员变量、一个方法
*/
@interface ViewController ()
@property (nonatomic, strong)Car *zuoDiHu;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.zuoDiHu = [[Car alloc]init];
self.zuoDiHu.name = @"法拉利";
[self changeInstanceVolume];
////method_exchangeImplementations
[self exchangeInstanceMethod];
////class_addMethod
[self addMethodForInstance];
[self.zuoDiHu guess];
////给Category添加属性
////先为扩展类声明需要添加的属性
///char runTime
/// objc_getAssociatedObject///设置getter
///objc_setAssociatedObject///设置setter
self.zuoDiHu.allTime = @"动态添加Category属性";
NSLog(@"%@",self.zuoDiHu.allTime);
}
///动态的更改成员变量的值
- (void)changeInstanceVolume
{
//① 动态获取Car类中的所有属性[当然包括私有]
unsigned int count = 0;
Ivar *ivar = class_copyIvarList([self.zuoDiHu class], &count);
//②遍历属性找到对应name字段
for (int i = 0; i < count; i ++) {
Ivar var = ivar[i];
const char *varName = ivar_getName(var);
NSString *name = [NSString stringWithUTF8String:varName];
//③修改对应的字段值成劳斯拉斯
if ([name isEqualToString:@"_name"]) {
object_setIvar(self.zuoDiHu, var, @"劳斯拉斯");
}
}
NSLog(@"%@",self.zuoDiHu.name);
}
////交换对象的方法
- (void)exchangeInstanceMethod
{
///①获取实例对象要交换的方法
Method method1 = class_getInstanceMethod([self.zuoDiHu class], @selector(runRun));
Method method2 = class_getInstanceMethod([self.zuoDiHu class], @selector(stopStop));
///②进行方法交换
method_exchangeImplementations(method1, method2);
[self.zuoDiHu runRun];
[self.zuoDiHu stopStop];
}
///动态的给类添加方法
- (void)addMethodForInstance
{
///①动态给Car类中添加guess方法:
class_addMethod([self.zuoDiHu class], @selector(guess), (IMP)guessAnswer, "v@:");
}
void guessAnswer(id self,SEL _cmd){
NSLog(@"动态的给类添加方法");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦