交换方法
交换方法:使用场景:系统自带的功能不够,给系统自带的方法扩展一些功能,并且保持原有的功能。
方式1:继承系统的类,重写方法
方式2:使用runtime交换方法
例如:我们现在要在控制器中加载一张图片。
//用这个方法加载图片,并不知道图片是否加载成功
UIImage *img = [UIImage imageNamed:@"111"];
一般的做法,我们会给UIImage创建一个分类,先创建一个分类:UIImage+img
,然后重新写一个类方法,来判断是否加载成功。
+ (__kindof UIImage *)home_imageNamed:(NSString *)imageName;
+ (__kindof UIImage *)home_imageNamed:(NSString *)imageName
{
//1.加载图片
UIImage *img = [UIImage imageNamed:imageName];
//2.判断功能
if (img == nil) {
NSLog(@"加载图片为空");
}
return img;
}
这样子,在控制器中,引入分类头文件,#import "UIImage+img.h"
,直接调用,可以实现判断是否加载成功。
但是,我们每次使用这个方法的时候,都需要导入头文件。现在我们通过runtime来实现调用imageNamed,底层调用:home_imageNamed。
在分类中,引入runtime头文件 #import <objc/message.h>
,
加载分类时调用load方法。
//加载这个分类的时候调用
//交换方法实现,方法都是定义在类里面
+ (void)load
{
NSLog(@"%s",__func__);
/*
Class:获取哪个类方法
SEL:获取方法编号,根据SEL就能去对应的类找方法
*/
Method imageNamedMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
//home_imageNamed
Method home_imageNamedMethod = class_getClassMethod([UIImage class], @selector(home_imageNamed:));
//交换方法
method_exchangeImplementations(imageNamedMethod, home_imageNamedMethod);
}
//由于运行程序就会调用load,现在交换方法成功。
//在这个方法中,加载图片,得用home_imageNamed
+ (__kindof UIImage *)home_imageNamed:(NSString *)imageName
{
//1.加载图片
UIImage *img = [UIImage home_imageNamed:imageName];
//2.判断功能
if (img == nil) {
NSLog(@"加载图片为空");
}
return img;
}
现在交换方法写好了,我们在控制器中不需要引入分类头文件,直接调用imageNamed,运行程序。
2017-01-18 13:20:47.549 [73546:6523190] +[UIImage(img) load]
2017-01-18 13:20:47.596 [73546:6523190] 加载图片为空