在刚接触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);
}
});
}
- ( 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/
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。