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

基于@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; } 

UPDATE

忽略UI事件的另一种方法是[[UIApplication sharedApplication] beginIgnoringInteractionEvents][[UIApplication sharedApplication] endIgnoringInteractionEvents]

beginIgnoringInteractionEventsendIgnoringInteractionEvents将阻止应用程序的所有触摸事件,直到调用endIgnoringInteractionEvents

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

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