performselector 取消(iOS--按钮快速点击多次响应的解决办法)

主要是记录一下按钮的多次点击

在刚接触iOS开发,刚写的iOS点击肯定不会考虑到如何去优化一个按钮的重复点击。在现实开发的过程,如果快速的点击同一个按钮,这个按钮对应的实现事件会被多次执行,这样子虽然不是错的,但是体验效果不好。

解决思路

刚开始肯定会想到这样子,我们触发了按钮(UIButton),UIButton在继承于UIControl,这个UIControl有enabled这个属性,可以触发了按钮就把enabled设置成No,等执行完之后在把enabled设置成Yes,这是一种解决办法,但是面试官会认为你好土。 第二种思路,UIControl是继承于UIView,UIView有userInteractionEnabled这个属性,也可以设置成Yes和No,但是这样子的回答入职的机会基本等于0。那我们要怎么办呢? 那就有了第三种方法,那就是运用到了运行时的东西runtime,我们可以给UIControl或者UIButton写一个分类:

在.h文件声明两个属性

@property ( nonatomic , assign ) NSTimeInterval * timeInterval;

@property ( nonatomic , assign)BOOL isIgnoreEvent ;

在.m文件引入 #import <objc/runtime.h> 并声明一个默认的间隔时间 #define defaultInterval 0

之后具体的代码如下: - ( NSTimeInterval ) timeInterval {

return [ objc_getAssociatedObject ( self , _cmd ) doubleValue ];

}

- ( void ) setTimeInterval :( NSTimeInterval )timeInterval{

objc_setAssociatedObject ( self , @selector (timeInterval), @( timeInterval ) ,OBJC_ASSOCIATION_RETAIN_NONATOMIC );

}

- ( BOOL ) isIgnoreEvent {

return [ objc_getAssociatedObject ( self , _cmd ) boolValue ];

}

- ( void ) setIsIgnoreEvent :( BOOL )isIgnoreEvent{

objc_setAssociatedObject ( self , @selector (isIgnoreEvent), @( isIgnoreEvent ) ,OBJC_ASSOCIATION_RETAIN_NONATOMIC );

}

- ( void ) resetState {

[ self setIsIgnoreEvent : NO ];

}

+ ( void ) load {

static dispatch_once_t onceToken;

dispatch_once (&onceToken, ^{

SEL selA = @selector (sendAction:to:forEvent:);

SEL selB = @selector (lyzSendAction:to:forEvent:);

Method methodA = class_getInstanceMethod ( self , selA);

Method methodB = class_getInstanceMethod ( self , selB);

BOOL isAdd = class_addMethod ( self , selA, method_getImplementation (methodB), method_getTypeEncoding(methodB));

if (isAdd) { =class_replaceMethod ( self , selB, method_getImplementation (methodA), method_getTypeEncoding(methodA));

} else {

method_exchangeImplementations (methodA, methodB);

performselector

}

});

}

- ( void ) lyzSendAction :( SEL )action to :( id )target forEvent :( UIEvent *)event{

if ([ NSStringFromClass ( self . class ) isEqualToString : @"UIButton" ]) {

self . timeInterval = self . timeInterval == 0 ? defaultInterval : self . timeInterval ;

if ( self . isIgnoreEvent ) {

return ;

} else if ( self . timeInterval > 0 ){

[ self performSelector : @selector (resetState) withObject : nil afterDelay : self . timeInterval ];

}

}

self . isIgnoreEvent = YES ;

[ self lyzSendAction :action to :target forEvent :event];

}

在viewController调用如下:

UIButton * btn = [ UIButton buttonWithType : UIButtonTypeCustom ];

btn. frame = CGRectMake ( 100 , 100 , 50 , 50 );

btn. backgroundColor = [ UIColor redColor ];

[btn setTitle : @"点我" forState : 0 ];

btn. timeInterval = 2 ;

[btn addTarget : self action : @selector (touch) forControlEvents : UIControlEventTouchUpInside ];

[ self . view addSubview :btn];


作者:我是小黑黑
链接:https://juejin.cn/post/7048834691146711076/
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

您可以还会对下面的文章感兴趣

使用微信扫描二维码后

点击右上角发送给好友