RunTime机制详解(三)

方法交换(Method Swizzling),先来看看这两张图片了解一下方法的实现的步骤(图片来源于网络)。

一、方法未交前SEL与IMP是这样的一一对应。


二、交换后SEL与IMP是这样的对应关系。


三、具体代码的实现是下面这样。

+ (void)swizzleSelector:(SEL)originalSelector withSwizzledSelector:(SEL)swizzledSeletor{
    Class class = [self class];
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzleMethod = class_getInstanceMethod(class, swizzledSeletor);
    
    //若已经存在,则添加失败
    BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
    //若原来的方法并不存在,则添加即可
    if (didAddMethod) {
        class_replaceMethod(class, swizzledSeletor, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    }else{
        method_exchangeImplementations(originalMethod, swizzleMethod);
    }
}

四、方法交换的实际应用。——防止按钮重复点击。

(1)主要应用到了RunTime机制的动态添加属性和方法交换。

(2)在UIButton的类别中.h文件添加属性,timeInterval(表示第一次点击几秒之后再次点击才会响应)。

(3)动态添加属性。

#pragma mark --- 动态添加属性
- (NSTimeInterval)timeInterval{
    return [objc_getAssociatedObject(self, ButtonTimeInterval) doubleValue];
}
- (void)setTimeInterval:(NSTimeInterval)timeInterval{
    objc_setAssociatedObject(self, ButtonTimeInterval, @(timeInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
(4)方法交换。

#pragma mark --- load方法内进行方法互换(这个方法只会在初始化被调用一次)
+ (void)load{

    [self swizzleSelector:@selector(sendAction:to:forEvent:) withSwizzledSelector:@selector(custom_sendAction:to:forEvent:)];
  
}
(5)在自定义的要交换的方法中实现想要的效果。

#pragma mark --- 自定义方法的实现
- (void)custom_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
    if (self.pass)return;
    if (self.timeInterval > 0) {
        self.pass = YES;
        [self performSelector:@selector(resetPassValue) withObject:nil afterDelay:self.timeInterval];
    }
    [self custom_sendAction:action to:target forEvent:event];
}
- (void)resetPassValue{
    [self setPass:NO];
}

(6)聪明的你肯定是知道为什么最后自定的方法要实现自己调用自己呢?这才是方法交换的本质嘛,调用自己其实就是在调用系统的实现方法。

代码传送门:https://github.com/fuzongjian/Runtime_ButtonClick.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值