RunTime
RunTime(运行时)是属于OC的一套底层实现,可以实现一些OC无法实现的底层操作。
当初学习RunTime的时候网上的资料也是琳琅满目,没一个看的懂得(我C语言功底比较差)。
下面我整理下自己的学习笔记,适合基础比较薄弱的同学学习
RunTime的常见操作:
<pre>
1.利用RunTime,在程序运行的过程中动态的创建一个类。
2.利用RunTime,在程序运行的过程中,动态的为某个类添加/修改 方法和属性。
3.遍历一个类的所有的成员变量和方法
</pre>
RunTime的用法:
<pre>
1.导入头文件<objc/runtime> <objc/message>
RunTime中的:
typedef struct objc_method *Method; 成员方法
typedef struct objc_ivar *Ivar; 成员属性
Ivar *class_copyIvarList 拷贝出一个对象的所有的成员变量列表
Method *class_copyMethodList 拷贝出一个对象的所有的成员方法列表
Message中的:
objc_msgSend 给某个对象发送消息
objc_msgSendSuper 给某个对象的父类发送消息
</pre>
利用RunTime交换两个方法的实现
首先定义一个person类,在.h中声明两个方法并在.m中实现两个方法
<pre>
import <Foundation/Foundation.h>
@interface Person : NSObject
.h
- (void)run;
- (void)study;
@end
.m
import "Person.h"
@implementation Person
- (void)run
{
NSLog(@"跑");
} - (void)study
{
NSLog(@"学习");
}
@end
</pre>
然后回到我们的ViewController中,引入需要用到的头文件
<pre>
import "ViewController.h"
import "Person.h"
import <objc/runtime.h>
import <objc/message.h>
</pre>
<pre>/**
* 交换两个两个类的方法的实现
*/
// 第一次打印
[Person run];
[Person study];
// 拿到.h中的两个方法
Method m1 = class_getClassMethod([Person class], @selector(run));
Method m2 = class_getClassMethod([Person class], @selector(study));
method_exchangeImplementations(m1, m2);
NSLog(@"runtime交换后");
// 方法交换后打印
[Person run];
[Person study];
</pre>
![Uploading ECB8161F-58E0-4170-A8C2-E1F1F718CB51_146663.png . . .]
通过RunTime我们也可以拦截到系统的方法并重写系统方法
以UIImage的imageNamed:为例,我们首先为UIImage创建一个Category,并在.h中定义我们需要重写的方法
<pre>
import <UIKit/UIKit.h>
@interface UIImage (Category)
// 自定义一个方法,改变image的图片加载的系统方法,方法中写入要在系统方法中加入的语句(eg:版本判断)
- (UIImage *)kk_imageNamed:(NSString *)name;
@end
</pre>
<pre>#import "UIImage+Category.h"
import <objc/runtime.h>
@implementation UIImage (Category)
- (UIImage *)kk_imageNamed:(NSString *)name
{
double version = [[UIDevice currentDevice].systemVersion doubleValue];
if (version >= 7.0) {
// 如果系统版本是7.0以上,使用另外一套文件名结尾是‘_OS7’的扁平化图片
name = [name stringByAppendingString:@"_OS7"];
}
return [UIImage kk_imageNamed:name];
} - (void)load
{
// 获取两个方法
Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
Method m2 = class_getClassMethod([UIImage class], @selector(kk_imageNamed:));
// 交换两个方法的实现
method_exchangeImplementations(m1, m2);
}
@end
回到ViewController中
/**- 重写系统的方法
*/
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 300, 100)];
UIImage *image = [UIImage imageNamed:@"test"];
imageView.image = image;
[self.view addSubview:imageView];
</pre>
- 重写系统的方法