1:好比咱們有個需求:讓UIImage加載圖片的時候,告訴咱們是否加載成功了swift
前言:spa
/**
Runtime(交換方法):只要是想修改系統的方法實現
* 1: 需求:讓UIImage加載圖片,告訴我是否加載成功、給系統UIImageName添加功能,只能使用Runtime
* 2: //解決辦法一:自定義UIImage方法、重寫:能夠解決
* 弊端:1:每次使用,都須要導入
2:若是項目開發好久了,如今這樣一個一個改很麻煩
* 3: //解決辦法二:只能給UIImage添加分類,使用Runtime
1:給系統的方法添加一個分類
2:本身實現一個帶有拓展功能的方法
3:交換方法,只須要交換一次
*/code
> 01-咱們想到的方法可能就是自定義UIImage類,拓展這個方法:如圖片
#import <UIKit/UIKit.h> @interface XJUIImage : UIImage + (UIImage *)imageNamed:(NSString *)name ; @end #import "XJUIImage.h" @implementation XJUIImage + (UIImage *)imageNamed:(NSString *)name { UIImage *image = [super imageNamed:name]; if (image) { NSLog(@"加載成功"); }else { NSLog(@"加載失敗"); } return image; } @end
而後調用的時候:先導入頭文件內存
#import "XJUIImage.h"
最後使用:開發
- (void)viewDidLoad { [super viewDidLoad]; UIImage *image = [XJUIImage imageNamed:@"1.png"]; //UIImage *image = [UIImage xj_imageNamed:@"2.png"]; //UIImage *image = [UIImage imageNamed:@"3"]; }
最後就會打印 加載成功 || 加載失敗get
注意:上面這種思路,能夠解決了問題,可是它有一些弊端:it
> 01-每次使用,都須要導入頭文件io
> 02-若是項目已經開發好久了,你不可能全局的一個一個的這樣修改,直接搞死你class
> 02-咱們可能想要建立一個UIImage分類:可是你若是不使用runtime的話,你仍是須要每次導入頭文件,仍是須要修改方法名
// 在分類中,最好不要重寫系統的辦法,通常重寫了,就把系統方法給覆蓋了 //+ (UIImage *)imageNamed:(NSString *)name { // //super:指向父類,因此在分類不能調用super //}
#import "UIImage+XJImage.h"
UIImage *image = [UIImage xj_imageNamed:@"2.png"];
注意:它的弊端和上面是同樣的問題,不能很好的幫助咱們解決問題。
> 03-使用runtime:交換方法:
#import <UIKit/UIKit.h> @interface UIImage (XJImage) + (UIImage *)xj_imageNamed:(NSString *)name; @end #import "UIImage+XJImage.h" #import <objc/message.h> @implementation UIImage (XJImage) // 在分類中,最好不要重寫系統的辦法,通常重寫了,就把系統方法給覆蓋了 //+ (UIImage *)imageNamed:(NSString *)name { // //super:指向父類,因此在分類不能調用super //} // 把類加載進內存的時候調用,只會調用一次 + (void)load { // 交換方法:runtime // 獲取imageNamed Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:)); // 獲取xj_imageNamed Method xj_imageNameMethod = class_getClassMethod(self, @selector(xj_imageNamed:)); method_exchangeImplementations(imageNameMethod, xj_imageNameMethod); } // 還有一種方式:可是會調用屢次,咱們能夠結合dispatch_once_t:保證只會執行一次,swift中只能使用這個方法,由於swift中沒有load方法 + (void)initialize { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ }); } // 之後想修改系統的方法,可是又不想重名字,能夠在前面添加前綴 + (UIImage *)xj_imageNamed:(NSString *)name { UIImage *image = [UIImage xj_imageNamed:name]; if (image) { NSLog(@"xj--加載成功了"); }else { NSLog(@"xj--加載失敗了"); } return image; } @end
注意:它的好處:
意見反饋郵件:1415429879@qq.com 歡迎大家的閱讀和讚揚、謝謝!