AFNetworking 的作者在它的源碼中就用到了這個方法,這是一個很高級的方法,但是他本人卻不建議使用,雖然如此,還是分享給大家.
這個方法的原理就是三行代碼:
Snip20161211_11.png
AFURLSessionManager.m 文件的第 324到328行
static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) {
Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
交換了originalMethod 與 swizzledMethod
注意:
調用 originalSelector 方法就是調用 swizzledSelector 方法;
調用 swizzledSelector 方法就是調用 originalSelector 方法;
主 Bundle 欄
Snip20161211_9.png
**ViewController.m 文件"
**
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(99, 99, 200, 200)] ;
[self.view addSubview:iv] ;
iv.image = [UIImage imageNamed:@"01"] ;
}
@end
UIImageView+HackExtension.h 文件
#import <UIKit/UIKit.h>
@interface UIImageView (HackExtension)
@end
UIImageView+HackExtension.m 文件
#import "UIImageView+HackExtension.h"
#import <objc/runtime.h>
@implementation UIImageView (HackExtension)
//在類別加載到運行時的時候,就會執行這個方法:
+ (void)load {
//1.獲取 UIImageView 的實例方法該方法位于本類,方法名為 setImage:
Method originalMethod = class_getInstanceMethod([self class], @selector(setImage:)) ;
//1.獲取 UIImageView 的實例方法該方法位于本類,方法名為 MD_setImage:
Method swizzledMethod = class_getInstanceMethod([self class], @selector(MD_setImage:)) ;
//3.交換方法:setImage 和 MD_setImage
//重點!!!調用 setImage 相當于調用 MD_setImage, 調用 MD_setImage 相當于調用 setImage 切記!!!
method_exchangeImplementations(originalMethod, swizzledMethod) ;
}
/**
* 1.當在其他位置調用 'setImage'方法時, '自動'調用 MD_setImage 方法:
*/
- (void)MD_setImage:(UIImage *)image {
NSLog(@"%s---- %@" ,__FUNCTION__ , image) ;
//1.根據 imageView 的大小,重新調整 image 的尺寸大小:
//要搞一個嚴絲合縫的跟圖片大小一樣的 imageView:
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0) ;
//繪制圖像:
[image drawInRect:self.bounds] ;
//取得結果:
//從當前圖片上下文中獲得圖片:
UIImage *result = UIGraphicsGetImageFromCurrentImageContext() ;
//關閉圖片上下文:
UIGraphicsEndImageContext() ;
//交換方法之后系統就不會平行調用 setImage 方法了,我們要在這里去調用 setImage 方法:
//而且!原有的 setImage 方法名也不叫 setImage 了,而是交換為了 MD_setImage 方法!!!切記!切記~
[self MD_setImage:result] ;
//如果這里按照下面這么寫!!!!那就是死循環!!!!切記!!!
// [self setImage:image] ;
}
@end