一, 使用runtime实现方法的交换
一, 前言
-
在开发过程中,我们常常会遇到一种问题: 即当我们使用系统自带的方法时,发现系统方法的功能不能满足我们的需求,这时候需要我们给系统的方法添加额外的功能.
-
下面以一个例子来实现给系统自带的方法添加额外的功能.
-
项目背景 : 公司有个开发了很久的项目,之前使用添加图片的方法用的是:imageName:方法, 现在的项目需求是给系统自带的imageName:添加一个功能:如果下载的图片不存在,那么就提示我们当前下载的图片为空.
-
思路 : 给系统自带的方法添加功能的几种方法
- 1, 自定义类, 重写系统自带的imageName:方法,这种方法虽然可以实现,但是它的弊端就是必须要使用自己的类,依赖性强.
- 2, 个UIImage添加一个分类, 改变系统类的实现,给系统的类添加方法的时候调用(强烈不推荐)
- 3, 使用runtime的交互方法,给系统的方法添加功能. 具体实现 : 添加一个分类 --> 在分类中提供一个需要添加的功能的方法 --> 将这个方法的实现和系统自带的方法的实现交互.
二, 步骤
- 1, 新建一个继承自UIImage的分类,定义一个方法实现给系统的自带的方法添加功能.
#import <UIKit/UIKit.h>
@interface UIImage (WGImage)
// 声明方法
// 如果跟系统方法差不多功能,可以采取添加前缀,与系统方法区分
+ (UIImage *)wg_imageWithName:(NSString *)imageName;
@end
- 2, 实现方法的交互
定义完毕新方法后,需要弄清楚什么时候实现与系统的方法交互?
答 : 既然是给系统的方法添加额外的功能,换句话说,我们以后在开发中都是使用自己定义的方法,取代系统的方法,所以,当程序一启动,就要求能使用自己定义的功能方法.说道这里:我们必须要弄明白一下两个方法 :
+(void)initialize(当类第一次被调用的时候就会调用该方法,整个程序运行中只会调用一次)
+ (void)load(当程序启动的时候就会调用该方法,换句话说,只要程序一启动就会调用load方法,整个程序运行中只会调用一次)
+ (void)load {
/*
self:UIImage
谁的事情,谁开头 1.发送消息(对象:objc) 2.注册方法(方法编号:sel) 3.交互方法(方法:method) 4.获取方法(类:class)
Method:方法名
获取方法,方法保存到类
Class:获取哪个类方法
SEL:获取哪个方法
imageName
*/
// 获取imageName:方法的地址
Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:));
// 获取wg_imageWithName:方法的地址
Method wg_imageWithNameMethod = class_getClassMethod(self, @selector(wg_imageWithName:));
// 交换方法地址,相当于交换实现方式
method_exchangeImplementations(imageNameMethod, wg_imageWithNameMethod);
}
- 3, 加载图片, 判断当前图片是否为空
// 加载图片, 判断是否为空
+ (UIImage *)wg_imageWithName:(NSString *)imageName
{
// 这里调用imageWithName,相当于调用imageName
UIImage *image = [UIImage wg_imageWithName:imageName];
if (!image) {
NSLog(@"Alex : 图片不存在");
}
return image;
}
- 4, 使用交互后的方法
#import "ViewController.h"
#import "WGStudent.h"
#import "UIImage+WGImage.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// wg_imageWithName ---> imageNamed(底层的操作 : 1, 下载图片. 2, 判断图片是否存在 )
[UIImage imageNamed:@"WilliamAlex.png"];
}
@end
- 5, 打印结果
2016-03-08 17:29:50.372 fdsfsdf[1545:96854] Alex : 图片不存在
知识拓展
- 不能在分类中重写系统方法imageNamed,因为会把系统的功能给覆盖掉,而且分类中不能调用super.
网友评论