1 方法調(diào)用機(jī)制

- 本質(zhì)是讓對象發(fā)送消息.對象方法保存到類中,每個類都有一個方法列表
- (1)根據(jù)對象的isa指針找到對應(yīng)的類
- (2)根據(jù)方法編號查找到方法名
- (3)根據(jù)方法名找到函數(shù)實(shí)現(xiàn),方法名就是函數(shù)入口
2 交換方法的實(shí)現(xiàn)機(jī)制

3 交換方法使用舉例
場景: 有個項(xiàng)目,已經(jīng)開發(fā)2年多了,之前加載圖片都是用UIImage,忽然有一天,老大說給我寫一個加載圖片方法,判斷是否成功加載圖片
常用思路:
- (1)直接添加判斷
// 1.加載圖片
UIImage *image = [UIImage imageNamed:@"abc"];
// 2.判斷
if (image) {
NSLog(@"加載成功");
} else {
NSLog(@"加載失敗");
}
備注:封裝性不好,到處都需要寫判斷代碼
(2)分類中重寫系統(tǒng)的imageNamed(不推薦,會把系統(tǒng)方法覆蓋掉)
(3)自定義image
創(chuàng)建一個繼承自UIImage的類,實(shí)現(xiàn)方法:
+ (UIImage *)imageNamed:(NSString *)name
{
// 加載圖片
// super:UIImage
UIImage *image = [super imageNamed:name];
if (image) {
NSLog(@"加載成功");
} else {
NSLog(@"加載失敗");
}
return image;
}
備注:只能在后期開發(fā)過程中使用,如果之前圖片加載的地方都要做判斷,需要把所有的UIImage換成自定義的MyImage,工作量大.
- (4)runtime交換方法實(shí)現(xiàn)(推薦)
1.創(chuàng)建一個UIImage的分類,自定義my_imageNamed方法
+ (UIImage *)xmg_imageNamed:(NSString *)name
{
// 1.加載圖片
UIImage *image = [UIImage xmg_imageNamed:name];
// 2.判斷
if (image) {
NSLog(@"加載成功");
} else {
NSLog(@"加載失敗");
}
return image;
}
2. 在load方法中實(shí)現(xiàn)方法交換
// 保證在所有方法之前交換,只會調(diào)用一次
+ (void)load
{
// 獲取imageName方法
Method imageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));
// 獲取MY_imageNamed方法(自定義的方法)
Method my_imageNamedMethod = class_getClassMethod(self, @selector(my_imageNamed:));
// 利用runtime交換方法
method_exchangeImplementations(imageNamedMethod, my_imageNamedMethod);
}
備注:交換以后,調(diào)用imageNamed方法,實(shí)質(zhì)實(shí)現(xiàn)的是my_imageNamed方法;調(diào)用my_imageNamed方法,實(shí)質(zhì)實(shí)現(xiàn)的是imageNamed方法;