交换方法
交换方法:使用场景:系统自带的功能不够,给系统自带的方法扩展一些功能,并且保持原有的功能。 方式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] 加载图片为空复制代码