一, 使用runtime實(shí)現(xiàn)方法的交換
一, 前言
在開發(fā)過程中,我們常常會(huì)遇到一種問題: 即當(dāng)我們使用系統(tǒng)自帶的方法時(shí),發(fā)現(xiàn)系統(tǒng)方法的功能不能滿足我們的需求,這時(shí)候需要我們給系統(tǒng)的方法添加額外的功能.
下面以一個(gè)例子來實(shí)現(xiàn)給系統(tǒng)自帶的方法添加額外的功能.
項(xiàng)目背景 : 公司有個(gè)開發(fā)了很久的項(xiàng)目,之前使用添加圖片的方法用的是:imageName:方法, 現(xiàn)在的項(xiàng)目需求是給系統(tǒng)自帶的imageName:添加一個(gè)功能:如果下載的圖片不存在,那么就提示我們當(dāng)前下載的圖片為空.
-
思路 : 給系統(tǒng)自帶的方法添加功能的幾種方法
- 1, 自定義類, 重寫系統(tǒng)自帶的imageName:方法,這種方法雖然可以實(shí)現(xiàn),但是它的弊端就是必須要使用自己的類,依賴性強(qiáng).
- 2, 個(gè)UIImage添加一個(gè)分類, 改變系統(tǒng)類的實(shí)現(xiàn),給系統(tǒng)的類添加方法的時(shí)候調(diào)用(強(qiáng)烈不推薦)
- 3, 使用runtime的交互方法,給系統(tǒng)的方法添加功能. 具體實(shí)現(xiàn) : 添加一個(gè)分類 --> 在分類中提供一個(gè)需要添加的功能的方法 --> 將這個(gè)方法的實(shí)現(xiàn)和系統(tǒng)自帶的方法的實(shí)現(xiàn)交互.
二, 步驟
- 1, 新建一個(gè)繼承自UIImage的分類,定義一個(gè)方法實(shí)現(xiàn)給系統(tǒng)的自帶的方法添加功能.
#import <UIKit/UIKit.h>
@interface UIImage (WGImage)
// 聲明方法
// 如果跟系統(tǒng)方法差不多功能,可以采取添加前綴,與系統(tǒng)方法區(qū)分
+ (UIImage *)wg_imageWithName:(NSString *)imageName;
@end
- 2, 實(shí)現(xiàn)方法的交互
定義完畢新方法后,需要弄清楚什么時(shí)候?qū)崿F(xiàn)與系統(tǒng)的方法交互?
答 : 既然是給系統(tǒng)的方法添加額外的功能,換句話說,我們以后在開發(fā)中都是使用自己定義的方法,取代系統(tǒng)的方法,所以,當(dāng)程序一啟動(dòng),就要求能使用自己定義的功能方法.說道這里:我們必須要弄明白一下兩個(gè)方法 :
+(void)initialize(當(dāng)類第一次被調(diào)用的時(shí)候就會(huì)調(diào)用該方法,整個(gè)程序運(yùn)行中只會(huì)調(diào)用一次)
+ (void)load(當(dāng)程序啟動(dòng)的時(shí)候就會(huì)調(diào)用該方法,換句話說,只要程序一啟動(dòng)就會(huì)調(diào)用load方法,整個(gè)程序運(yùn)行中只會(huì)調(diào)用一次)
+ (void)load {
/*
self:UIImage
誰的事情,誰開頭 1.發(fā)送消息(對象:objc) 2.注冊方法(方法編號(hào):sel) 3.交互方法(方法:method) 4.獲取方法(類:class)
Method:方法名
獲取方法,方法保存到類
Class:獲取哪個(gè)類方法
SEL:獲取哪個(gè)方法
imageName
*/
// 獲取imageName:方法的地址
Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:));
// 獲取wg_imageWithName:方法的地址
Method wg_imageWithNameMethod = class_getClassMethod(self, @selector(wg_imageWithName:));
// 交換方法地址琼开,相當(dāng)于交換實(shí)現(xiàn)方式
method_exchangeImplementations(imageNameMethod, wg_imageWithNameMethod);
}
- 3, 加載圖片, 判斷當(dāng)前圖片是否為空
// 加載圖片, 判斷是否為空
+ (UIImage *)wg_imageWithName:(NSString *)imageName
{
// 這里調(diào)用imageWithName规求,相當(dāng)于調(diào)用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, 打印結(jié)果
2016-03-08 17:29:50.372 fdsfsdf[1545:96854] Alex : 圖片不存在
知識(shí)拓展
- 不能在分類中重寫系統(tǒng)方法imageNamed欢嘿,因?yàn)闀?huì)把系統(tǒng)的功能給覆蓋掉际度,而且分類中不能調(diào)用super.