iOS開發(fā)禁用多個(gè)按鈕同時(shí)點(diǎn)擊導(dǎo)致誤觸

iOS開發(fā)禁用多個(gè)按鈕同時(shí)點(diǎn)擊導(dǎo)致誤觸

在開發(fā)iOS項(xiàng)目的時(shí)候很多開發(fā)者都不會(huì)考慮這樣的一個(gè)問題,包括我也不會(huì)------一個(gè)界面內(nèi)有多個(gè)按鈕或者touch事件同時(shí)進(jìn)行會(huì)怎么樣?

單從字面上看可能不容易理解,舉個(gè)比較容易理解的例子.
在某個(gè)應(yīng)用的首頁上,有兩個(gè)按鈕,我們單獨(dú)的點(diǎn)擊每一個(gè)按鈕都會(huì)觸發(fā)一次點(diǎn)擊事件,這個(gè)本身沒有任何毛病,類似于點(diǎn)擊第一個(gè)按鈕跳轉(zhuǎn)到第一個(gè)子界面,點(diǎn)擊第二個(gè)按鈕跳轉(zhuǎn)到第二個(gè)子界面.但是我們是做的移動(dòng)開發(fā),我們會(huì)不會(huì)有過這樣的尷尬呢?我們手指比較粗,或者多個(gè)手指同事操作, 偶然間的我們會(huì)發(fā)生誤觸,導(dǎo)致一個(gè)尷尬的場景------兩個(gè)按鈕同時(shí)點(diǎn)擊了,那么樣的結(jié)果就是,會(huì)閃現(xiàn)兩次跳轉(zhuǎn)頁面,即跳轉(zhuǎn)第一個(gè)子界面和跳轉(zhuǎn)第二個(gè)子界面都會(huì)發(fā)生.很顯然這個(gè)不是我們想要的.那么怎么屏蔽呢?

1.我們可能會(huì)想到禁用按鈕點(diǎn)擊的方式,如果按鈕1點(diǎn)擊了,立刻禁止按鈕2的點(diǎn)擊,事件結(jié)束后開啟按鈕2的點(diǎn)擊,同樣的按鈕2頁做類似的操作,
實(shí)驗(yàn)下來有效么? 不能說完全無效,如果禁止按鈕點(diǎn)擊的代碼已經(jīng)實(shí)現(xiàn)了的話.
我們多次嘗試,還是會(huì)發(fā)現(xiàn)有誤觸現(xiàn)象.這個(gè)方法原理上行得通,但是,真正點(diǎn)擊的時(shí)候,你會(huì)發(fā)現(xiàn)禁止按鈕點(diǎn)擊的實(shí)現(xiàn)和點(diǎn)擊按鈕的事件的先后并不能完全保證...
如果兩次點(diǎn)擊稍微錯(cuò)開一點(diǎn)點(diǎn)時(shí)間差是沒有問題的,但是如果兩次點(diǎn)擊很接近就會(huì)出現(xiàn)問題.
如果是這樣的狀態(tài),沒有問題


這里寫圖片描述

但是如果時(shí)間段上移一點(diǎn),則一樣沒有效果


這里寫圖片描述

當(dāng)然如果你說你可以采用延遲執(zhí)行的方式,保證每次執(zhí)行都會(huì)延遲操作,并且做判斷...當(dāng)然這樣復(fù)雜的操作是肯定可以實(shí)現(xiàn)的,但是很顯然太復(fù)雜了.
那么我們就沒有辦法了嗎?或者我們找找系統(tǒng)方法,看看有沒有能夠?qū)崿F(xiàn)的其他途徑.

2.很顯然,iOS開發(fā)的框架中是有這樣的方法的.


這里寫圖片描述

UIView的UIViewGeometry分類中有這樣的一個(gè)屬性.
很顯然,不是遇到這種特殊情況需求的開發(fā)者是很難去有機(jī)會(huì)了解這個(gè)屬性的.
這個(gè)屬性很簡單,從翻譯上看:獨(dú)家接觸 那么它就一個(gè)作用,防止誤觸(同時(shí)點(diǎn)擊).當(dāng)然,它默認(rèn)是NO,所以我們在開發(fā)中會(huì)有誤觸發(fā)生,只要我們設(shè)置為YES即可..

那么我們在開發(fā)中就會(huì)多寫一行代碼即可,在創(chuàng)建的時(shí)候. 類似于[button setExclusiveTouch:YES]; 或者button.exclusiveTouch = YES;
是的,你已經(jīng)嘗試到了結(jié)果,正是我們想要的,我們不會(huì)再發(fā)生那種尷尬的非邏輯上的錯(cuò)誤發(fā)生了,不懂代碼的老板在拿著你的應(yīng)用最起碼不會(huì)因?yàn)檫@個(gè)問題而說你不會(huì)開發(fā)了(回想剛剛開發(fā)的時(shí)候的我.....).

3.有了這么好的方法,我們能夠加以利用呢?很顯然我們在開發(fā)中基本上是不會(huì)有同時(shí)觸碰的事件居多的,真正需要同時(shí)觸碰的基本上應(yīng)該是沒有的(游戲除外...)
我們也都有了解iOS開發(fā)中的runtime機(jī)制.我們能否利用這個(gè),將這行代碼給直接寫好呢?
我想到了一個(gè)方法.所有的UIView添加到界面上很顯然都會(huì)需要這個(gè)方法,addSubview:

于是我就想到了創(chuàng)建一個(gè)分類,應(yīng)該會(huì)好點(diǎn)


#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的機(jī)制,讓view在被擁有者添加到視圖上的之前先設(shè)置exclusiveTouch屬性.

很顯然,以后我們在寫代碼的時(shí)候再也不需要關(guān)心這個(gè)了,所有的按鈕,所有的繼承或者來自UIView的都會(huì)默認(rèn)實(shí)現(xiàn),我們回顧一下,我們所有能觸發(fā)點(diǎn)擊的控件,有哪一個(gè)不是繼承自UIView的呢?

于是乎,我們完美的禁用了多個(gè)按鈕同時(shí)點(diǎn)擊導(dǎo)致誤觸的尷尬發(fā)生.

3.當(dāng)然上面的邏輯只是我的一個(gè)思路,我們也可以采用遍歷的方式啊
我們替換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顯示到屏幕的時(shí)候在viewDidAppear:中遍歷子視圖,當(dāng)然子視圖中是否有子視圖?這個(gè)是否也需要遍歷?這里也是需要開發(fā)者自己考慮的,是深度遍歷,還是廣度遍歷...這些都不在本博客討論范圍內(nèi)...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,070評論 25 709
  • 本文屬于原創(chuàng)文章。轉(zhuǎn)載請聯(lián)系作者。本文首發(fā)地址:http://www.itdecent.cn/p/0c913719...
    酷酷的哀殿閱讀 1,059評論 0 5
  • 攝影是述說內(nèi)心的方式。當(dāng)文字不足以表述時(shí)空時(shí),它可以生動(dòng)描述并引起共鳴。我攝影純粹表現(xiàn)內(nèi)心世界,所以是自我的。大家...
    每日愛圖閱讀 110評論 0 0
  • 提煉:解決沖突 采取共贏,而不是你贏我輸,我贏你輸。 解決過程: 一,界定問題 二,想出可能的解決方案 三,評估所...
    egomuff閱讀 163評論 0 0
  • ROS采用rosrun命令可以啟動(dòng)一個(gè)節(jié)點(diǎn),如果需要同時(shí)啟動(dòng)節(jié)點(diǎn)管理器(master)和多個(gè)節(jié)點(diǎn),就需要采用lau...
    marine0131閱讀 12,493評論 0 0

友情鏈接更多精彩內(nèi)容