开发过程中,我们经常会用到系统类,而它提供的方法又不能完全满足我们开发的需要,那么在此时,我们需要为系统自带的方法扩展一些功能,而且还要保证原有的功能可正常使用.假设咱们现在有这么一个需求,我们在调用系统的[UIImage imageNamed:@"runtime"];的时候,我们并不能判断有没有加载成功,所以我们想在加载图片的时候并判断是否加载成功。
方案1:
我们通常想到的就是分类,用分类添加一个方法,实现,然后在想要调用的地方导入头文件,去调用.
#import <UIKit/UIKit.h> @interface UIImage (Method) +(UIImage *)cdm_imageNamed:(NSString *)imageName; @end +(UIImage *)cdm_imageNamed:(NSString *)imageName { //首先加载图片 UIImage *image=[UIImage imageNamed:imageName]; //然后实现功能【判断是否为空】 if (image==nil) { NSLog(@"图片为空"); } return image; }
调用:
import "ViewController.h" #import "UIImage+Method.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //分类实现: UIImage *image = [UIImage cdm_imageNamed:@"cdm"]; }
方案2:
利用runtime交换方法,我们调用系统的方法 实际是调用我们的方法:
步骤1.在分类加载的时候+(void)load;交换方法的实现
步骤2.方法交换之前首先获取方法,因为交换方法的两个参数就是方法
步骤3.方法交换
+(void)load { // 交换方法实现,方法都是定义在类里面 // class_getInstanceMethod:获取对象 // class_getClassMethod:获取类方法 // IMP:方法实现 // imageNamed // Class:获取哪个类方法 // SEL:获取方法编号,根据SEL就能去对应的类找方法 Method imageMethod = class_getClassMethod([UIImage class], @selector(imageNamed:)); Method cmd_imageMethod = class_getClassMethod([UIImage class], @selector(cdm_imageNamed:)); //方法交换 method_exchangeImplementations(imageMethod, cmd_imageMethod); }
如果此时你认为完事了,调用系统的imageNamed方法,会造成死循环。因为我们在自定义的方法中加载图片调用的就是系统的imageNamed的方法,此时应该修改代码如下:
//运行时 +(UIImage *)cdm_imageNamed:(NSString *)imageName { //修改为我们自己的方法,防止死循环 UIImage *image=[UIImage cdm_imageNamed:imageName]; //然后实现功能【判断是否为空】 if (image==nil) { NSLog(@"图片为空"); } return image; }
调用实现:
- (void)viewDidLoad { [super viewDidLoad]; //分类实现: // UIImage *image = [UIImage cdm_imageNamed:@"cdm"]; //运行时实现: //调用imageNamed:实际上是调用cdm_imageNamed: UIImage *image = [UIImage imageNamed:@"cdm"]; }
效果图:
Demo地址:https://github.com/domanc/Method_Exchange.git
时间: 2024-10-06 19:28:11