我正在尝试找到一种方法来消耗按钮,而不是从响应链本身上,而是从绑定到该按钮的其他操作方法中。我到处都在寻找这种解决方案,但一直找不到。

例如,假设我设置了一个带有事件选择器的按钮:

[button addTarget:self action:@selector(handler1:) forControlEvents:UIControlEventTouchUpInside];

然后在代码的后面,根据特定的应用程序情况,我想为同一控件事件向同一按钮添加另一个事件处理程序:
[button addTarget:self action:@selector(handler2:) forControlEvents:UIControlEventTouchUpInside];

这可以正常工作,两个事件确实都被调用了。但是我的问题是,如果不从按钮中删除handler1,我该如何做,以便在调用handler2时,该事件被“消耗”并且不会调用handler1?

我遇到这种情况的原因是,我希望我的应用程序进入教程模式,在此模式下,我将在教程模式下将新事件动态绑定到按钮。本教程将指示用户点击某个按钮,但我希​​望忽略屏幕上其他按钮上的点击事件,基本上是迫使用户点击所请求的按钮以继续本教程。因此,当用户进入教程时,每个按钮都会获得一个新的TouchUpInside处理程序。我希望首先调用此新处理程序,并阻止原始处理程序执行。

我已经能够通过首先将所有原始事件获取到NSSet中,然后为所有现有事件调用[button removeTarget...]来实现被调用的功能。然后添加动态事件,然后重新添加集合中的所有原始事件。这在调试器中起作用,以表明我的动态事件确实被首先调用。
  • 例如:
  • handler1会在被按下时执行某些操作(按钮的默认处理程序)
  • handler2是动态添加的,并将与教程控制器通信,“消耗” tap事件(防止handler1执行)。

  • 当不在教程模式下时,我希望handler1仍然可以执行它应该做的事情,但是如果handler2存在,我希望该方法运行,那么可以防止调用handler1。我不能从按钮上丢失handler1,因为当教程结束时,我希望该应用程序能够按预期工作。另外,在某些情况下,我仍然希望调用handler1。

    那么,是否有可能消耗一个事件并阻止其他相关事件的发生?

    我尝试在handler2中执行[button resignFirstResponder],但这似乎不起作用。它仍然调用原始的按钮事件处理程序。

    最佳答案

    基于@danielquokka关于重写方法sendActionsForControlEvents:的想法,我将UIButton子类化并添加以下代码。它工作正常。触发事件后,它将阻止UI事件0.5秒。

    - (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
    {
        [super sendAction:action to:target forEvent:event];
        self.userInteractionEnabled = NO;
    
        ///! After handle UIEvent, block this button UI events for a while.
        [self performSelector:@selector(delayEnable) withObject:nil afterDelay:0.5];
    }
    
    - (void)delayEnable
    {
        self.userInteractionEnabled = YES;
    }
    

    更新

    忽略UI事件的另一种方法是[[UIApplication sharedApplication] beginIgnoringInteractionEvents][[UIApplication sharedApplication] endIgnoringInteractionEvents]
    beginIgnoringInteractionEventsendIgnoringInteractionEvents将阻止应用程序的所有触摸事件,直到调用endIgnoringInteractionEvents

    08-19 12:19