runtime方法交换

来源:互联网 发布:sql 删除标识列 编辑:程序博客网 时间:2024/05/07 12:47

当系统提供的方法不能满足我们的要求时,我们可以用runtime来对系统方法做进一步的包装,比如当我们在加载图片时,如果想要判断图片是否为空,如果为空则提示,不为空则加载

#import <UIKit/UIKit.h>@interface UIImage (img)+(instancetype)imageWithName:(NSString *)name;@end
#import "UIImage+img.h"#import <objc/runtime.h>@implementation UIImage (img)//加载到内存的时候调用+(void)load{    //获取imageWithName的方法实现    Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));    //获取imageNamed的方法实现    Method imageNamed = class_getClassMethod(self, @selector(imageNamed:));    //交换imageNamed和imageWithName的方法实现    method_exchangeImplementations(imageWithName, imageNamed);}+(instancetype)imageWithName:(NSString *)name{    UIImage *image = [UIImage imageWithName:name];    if (image == nil) {        NSLog(@"加载了空的图片");    }    return image;}@end

当调用imageWithName: 方法就会判断图片是否为空了;这里只涉及到了类方法,如果是实例方法该怎么交换呢???哎,这个问题问的好!!!

#import <UIKit/UIKit.h>@interface RuntimeViewController : UIViewController-(void)function1;+(void)function2;@end
#import "RuntimeViewController.h"#import <objc/runtime.h>@interface RuntimeViewController ()@end@implementation RuntimeViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.}-(void)function1{    NSLog(@"我是function1");}+(void)function2{    NSLog(@"我是function2");}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@end

调用这两个方法!!

RuntimeViewController *runtimeVC = [[RuntimeViewController alloc]init];    Method fun1 = class_getInstanceMethod([runtimeVC class], @selector(function1));    Method fun2 = class_getClassMethod([RuntimeViewController class], @selector(function2));    //交换之前    NSLog(@"交换之前的结果");    [runtimeVC function1];    [RuntimeViewController function2];    //交换之后    NSLog(@"交换之后的结果");    method_exchangeImplementations(fun1, fun2);    [runtimeVC function1];    [RuntimeViewController function2];

可以看到控制台打印结果

控制台打印结果!!

这里主要涉及到两个方法class_getInstanceMethod()和class_getClassMethod(),前者是获取实例方法,后者是获取类方法;

1 0