1 方法調用機制
- 本質是讓對象發送消息.對象方法保存到類中,每個類都有一個方法列表
- (1)根據對象的isa指針找到對應的類
- (2)根據方法編號查找到方法名
- (3)根據方法名找到函數實現,方法名就是函數入口
2 交換方法的實現機制
3 交換方法使用舉例
場景: 有個項目,已經開發2年多了,之前加載圖片都是用UIImage,忽然有一天,老大說給我寫一個加載圖片方法,判斷是否成功加載圖片
常用思路:
- (1)直接添加判斷
// 1.加載圖片
UIImage *image = [UIImage imageNamed:@"abc"];
// 2.判斷
if (image) {
NSLog(@"加載成功");
} else {
NSLog(@"加載失敗");
}
備注:封裝性不好,到處都需要寫判斷代碼
(2)分類中重寫系統的imageNamed(不推薦,會把系統方法覆蓋掉)
(3)自定義image
創建一個繼承自UIImage的類,實現方法:
+ (UIImage *)imageNamed:(NSString *)name
{
// 加載圖片
// super:UIImage
UIImage *image = [super imageNamed:name];
if (image) {
NSLog(@"加載成功");
} else {
NSLog(@"加載失敗");
}
return image;
}
備注:只能在后期開發過程中使用,如果之前圖片加載的地方都要做判斷,需要把所有的UIImage換成自定義的MyImage,工作量大.
- (4)runtime交換方法實現(推薦)
1.創建一個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方法中實現方法交換
// 保證在所有方法之前交換,只會調用一次
+ (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);
}
備注:交換以后,調用imageNamed方法,實質實現的是my_imageNamed方法;調用my_imageNamed方法,實質實現的是imageNamed方法;