iOS开发禁用多个按钮同时点击导致误触

news/2024/5/20 15:58:24

#iOS开发禁用多个按钮同时点击导致误触

在开发iOS项目的时候很多开发者都不会考虑这样的一个问题,包括我也不会------一个界面内有多个按钮或者touch事件同时进行会怎么样?

单从字面上看可能不容易理解,举个比较容易理解的例子. 在某个应用的首页上,有两个按钮,我们单独的点击每一个按钮都会触发一次点击事件,这个本身没有任何毛病,类似于点击第一个按钮跳转到第一个子界面,点击第二个按钮跳转到第二个子界面.但是我们是做的移动开发,我们会不会有过这样的尴尬呢?我们手指比较粗,或者多个手指同事操作, 偶然间的我们会发生误触,导致一个尴尬的场景------两个按钮同时点击了,那么样的结果就是,会闪现两次跳转页面,即跳转第一个子界面和跳转第二个子界面都会发生.很显然这个不是我们想要的.那么怎么屏蔽呢?

1.我们可能会想到禁用按钮点击的方式,如果按钮1点击了,立刻禁止按钮2的点击,事件结束后开启按钮2的点击,同样的按钮2页做类似的操作, 实验下来有效么? 不能说完全无效,如果禁止按钮点击的代码已经实现了的话. 我们多次尝试,还是会发现有误触现象.这个方法原理上行得通,但是,真正点击的时候,你会发现禁止按钮点击的实现和点击按钮的事件的先后并不能完全保证... 如果两次点击稍微错开一点点时间差是没有问题的,但是如果两次点击很接近就会出现问题. 如果是这样的状态,没有问题

但是如果时间段上移一点,则一样没有效果

当然如果你说你可以采用延迟执行的方式,保证每次执行都会延迟操作,并且做判断...当然这样复杂的操作是肯定可以实现的,但是很显然太复杂了. 那么我们就没有办法了吗?或者我们找找系统方法,看看有没有能够实现的其他途径.

2.很显然,iOS开发的框架中是有这样的方法的.

UIView的UIViewGeometry分类中有这样的一个属性. 很显然,不是遇到这种特殊情况需求的开发者是很难去有机会了解这个属性的. 这个属性很简单,从翻译上看:独家接触 那么它就一个作用,防止误触(同时点击).当然,它默认是NO,所以我们在开发中会有误触发生,只要我们设置为YES即可..

那么我们在开发中就会多写一行代码即可,在创建的时候. 类似于[button setExclusiveTouch:YES]; 或者button.exclusiveTouch = YES; 是的,你已经尝试到了结果,正是我们想要的,我们不会再发生那种尴尬的非逻辑上的错误发生了,不懂代码的老板在拿着你的应用最起码不会因为这个问题而说你不会开发了(回想刚刚开发的时候的我.....).

3.有了这么好的方法,我们能够加以利用呢?很显然我们在开发中基本上是不会有同时触碰的事件居多的,真正需要同时触碰的基本上应该是没有的(游戏除外...) 我们也都有了解iOS开发中的runtime机制.我们能否利用这个,将这行代码给直接写好呢? 我想到了一个方法.所有的UIView添加到界面上很显然都会需要这个方法,addSubview:

于是我就想到了创建一个分类,应该会好点


#import "UIView+Extension.h"
#import <objc/runtime.h>

@implementation UIView (Extension)

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL systemSel = @selector(addSubview:);
        SEL swizzSel = @selector(myAddSubview:);
        Method systemMethod = class_getInstanceMethod([self class], systemSel);
        Method swizzMethod = class_getInstanceMethod([self class], swizzSel);
        BOOL isAdd = class_addMethod(self, systemSel, method_getImplementation(swizzMethod), method_getTypeEncoding(swizzMethod));
        if (isAdd) {
            class_replaceMethod(self, swizzSel, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
        }else{
            method_exchangeImplementations(systemMethod, swizzMethod);
        }
    });
}

- (void)myAddSubview:(UIView *)view{
    if ([view respondsToSelector:@selector(setExclusiveTouch:)]) {
        [view setExclusiveTouch:YES];
    }
    [self myAddSubview:view];
}

@end
复制代码

采用runtime的机制,让view在被拥有者添加到视图上的之前先设置exclusiveTouch属性.

很显然,以后我们在写代码的时候再也不需要关心这个了,所有的按钮,所有的继承或者来自UIView的都会默认实现,我们回顾一下,我们所有能触发点击的控件,有哪一个不是继承自UIView的呢?

于是乎,我们完美的禁用了多个按钮同时点击导致误触的尴尬发生.

3.当然上面的逻辑只是我的一个思路,我们也可以采用遍历的方式啊 我们替换VC中viewDidAppear:的方法

#import "UIViewController+Extension.h"

@implementation UIViewController (Extension)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        
        SEL originalSelector = @selector(viewDidAppear:);
        SEL swizzledSelector = @selector(myViewDidAppear:);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (success) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

-(void)myViewDidAppear:(BOOL)animated{
    for (UIView * subview in self.view.subviews) {
		if ([subview respondsToSelector:@selector(setExclusiveTouch:)]) {
	        [subview setExclusiveTouch:YES];
	    }
    }
    [self myViewDidAppear:animated];
}

@end

复制代码

在viewController显示到屏幕的时候在viewDidAppear:中遍历子视图,当然子视图中是否有子视图?这个是否也需要遍历?这里也是需要开发者自己考虑的,是深度遍历,还是广度遍历...这些都不在本博客讨论范围内...

欢迎访问我的系列博客,刚刚开始写... 系列:iOS开发-前言+大纲 blog.csdn.net/spicyShrimp…


http://www.niftyadmin.cn/n/1999241.html

相关文章

一个女人给上帝的信

亲爱的上帝&#xff1a; 您好&#xff01; 众里寻他千百度&#xff0c;那人却在&#xff0c;茫茫人海不知处&#xff01;所以&#xff0c;仁慈的上帝&#xff0c;看在我这个夏娃已单身29年的份上&#xff0c;请让我结识这样一个亚当吧&#xff01; 1.很英俊,高大,没…

计算机网络技术学些什么,计算机网络技术具体学些什么啊?

网络编辑员需要学些什么&#xff1f;我昨天看网络编辑员国家职业标准1&#xff0e;职业概况1。1职业名称网络编辑员1。2 职业定义利用相关专业知识及计算机和网络等现代信息技术&#xff0c;从事互联网站内容建设的人员。1。3 职业等级本职业共设四个等级&#xff0c;分别为网络…

适合事业上升期男人的女人

适合事业上升期男人的女人 事业上升期的男人们&#xff0c;工作压力大&#xff0c;精神常得不到放松&#xff0c;很希望能有一个女人给自己一个爱的环境&#xff0c;来温暖一颗疲惫的心。诚然&#xff0c;好女人能给一个男人营造一个温馨的环境&#xff0c;但还没有女朋友的男人…

使用UIBezierPath和CAShapeLayer自定义圆形进度

直线的进度条并不能满足日常的开发需求&#xff0c;所以我们使用UIBezierPath和CAShapeLayer来自定义 一、需要用到的知识 1.UIBezierPath 贝塞尔曲线&#xff0c;可以画出我们想要的许多图形。 2.CAShapeLayer CALayer的子类&#xff0c;配合贝塞尔曲线实现我们的自定义控件。…

计算机考试第一题英语,(计算机英语试题及答案.doc

(计算机英语试题及答案KEY TO COMPUTER ENGLISH TESTPAPER ONE(120 minutes)Part One: Translate the following words from English into Chinese and vice versa. (10 points)template(模板)algorithm(算法)retrieve(检索)embed(把…嵌入)firmware(固件)topology(拓扑结构)me…

Android中JNI的使用方法

from://http://www.cnblogs.com/bastard/archive/2012/05/19/2508913.html Android中JNI的使用方法 首先看一下Android平台的框架图&#xff1a;&#xff08;网上盗用&#xff09; 可以看到Android上层的Application和ApplicationFramework都是使用Java编写&#xff0c; 底层包…

使用模式集成UML视图

使用模式集成UML视图关键字&#xff1a;UML视图摘要 模式 在系统组合&#xff08;合成&#xff09;期间对养成重用可重复设计和 体系结构 配置的习惯很重要。本论文研究关于模式的知识&#xff0c;它也可用于系统分析检验系统模型的完整性。为了支持自动分析过程&#xff0c;该…

计算机磁盘在线分区,电脑硬盘如何分区

本文介绍的是用FDISK在DOS状态下分区, 这个对初学者来说比较难懂,实际上目前也不是用的太多,了解下就行了。我们还可以通过其他可视化的软件来对硬盘进行分区。总结了下, 分区的情况不外乎以下几种&#xff1a;1. 新电脑装系统时候进行分区这个主要在装新机器时候用,磁盘上的数…