ios runtime swizMethod 拦截交换方法执行

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值