ios runtime swizMethod 拦截交换方法执行

来源:互联网 发布:sql round函数怎么用 编辑:程序博客网 时间:2024/06/14 14:59

1. 说明:随便创建一个页面,里面有一个button,然后点击下,可以看到打印结果(利用runtime实现了拦截效果)

#import "ViewController.h"#import <objc/runtime.h>@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad{    [super viewDidLoad];        [self sendMethodTest];}#pragma mark -- swizMethod test- (void)sendMethodTest{    UIButton *_ljBtn = [[UIButton alloc]init];    [_ljBtn setFrame:CGRectMake(100, 150, 150, 100)];    [_ljBtn setBackgroundColor:[UIColor grayColor]];    [_ljBtn setTitle:@"sendMethodTest" forState:UIControlStateNormal];    [_ljBtn addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:_ljBtn];}- (void)clicked:(id)sender{    NSLog(@"%s", __func__);}


2.创建一个UIControl的类别,来实现拦截动作。

#import "UIControl+LJControl.h"#import <objc/runtime.h>@implementation UIControl (LJControl)+ (void)load{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{                Method origMethod = class_getInstanceMethod([self class], @selector(sendAction:to:forEvent:));        SEL origsel = @selector(sendAction:to:forEvent:);        Method swizMethod = class_getInstanceMethod([self class], @selector(LJControl_sendAction:to:forEvent:));        SEL swizsel = @selector(LJControl_sendAction:to:forEvent:);        BOOL addMehtod = class_addMethod([self class], origsel, method_getImplementation(swizMethod), method_getTypeEncoding(swizMethod));        if (addMehtod)        {            class_replaceMethod([self class], swizsel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));        }                else        {            method_exchangeImplementations(origMethod, swizMethod);        }    });} //原方法的指针位置指向交换后的LJControl_sendAction方法。下面的是拦截方法- (void)LJControl_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{    NSLog(@"%s", __func__);    //交换后的方法指针指向的是原方法的指针,就是下面的这个函数。因为上面的方法已经交换过了,所以下面的是点击事件方法    [self LJControl_sendAction:action to:target forEvent:event];}@end

3.结果

控制台打印结果:

2017-02-07 16:28:51.419494 ljDemo[1741:679678] -[UIControl(LJControl) LJControl_sendAction:to:forEvent:]2017-02-07 16:28:51.419778 ljDemo[1741:679678] -[ViewController clicked:]


4.结论

从打印结果可以看出,点击事件的拦截方法先执行,点击事件方法后执行。通过上面的方法,可以做一些埋点工作或者用户行为数据的获取。


0 0
原创粉丝点击