具有多个操作的UIButton:如何防止其他操作被触发

时间:2014-10-02 21:13:45

标签: ios cocoa-touch uibutton

我试图找到一种方法来按下按钮,而不是从响应链本身,而是从绑定到该按钮的其他动作方法。我已经全神贯注地寻找这个解决方案,而且一直无法找到它。

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

[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],但这似乎不起作用。它仍然调用原始按钮事件处理程序。

3 个答案:

答案 0 :(得分:3)

基于覆盖方法sendActionsForControlEvents:的{​​{3}}想法,我将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]

在调用beginIgnoringInteractionEvents之前,

endIgnoringInteractionEventsendIgnoringInteractionEvents将阻止应用的所有触摸事件。

答案 1 :(得分:1)

如果您知道应用程序的当前状态(如教程等),那么最好只使用一个handler1。并添加到方法handler1的主体:if(mode == tutorial){tutorial} else {default}。

答案 2 :(得分:1)

您可以向UIButton(或它的子类)添加一个类别,覆盖方法sendActionsForControlEvents:仅为一个目标调用sendAction:to:forEvent:(有关这些方法的描述,请参阅UIControl上的文档)。