如何以编程方式将触摸事件伪造到UIButton?


183

我正在编写一些单元测试,并且由于这个特定应用程序的性质,让我尽可能地上UI链很重要。因此,我想做的是以编程方式触发按钮的按下,就好像用户已经按下了GUI

(是的,是的,我可以调用IBAction选择器,但是再次,此特定应用程序的性质使我必须伪造实际的按钮按下,以便IBAction从按钮本身进行调用,这一点很重要。)

首选的方法是什么?


您能解释为什么伪造按钮触摸而不是直接调用action方法很重要吗?确实没有实际差异。
Jasarien

1
@Jasarien:好吧,因为有区别!;)在我的应用中,多个按钮使用相同的操作方法,该方法根据按钮的标签解析行为方式。因此,单元测试除了通过该方法测试一个特定的代码路径外,(a)还需要对它们进行全部测试,并且(b)还要验证按钮是否正确接线。另外,它很好地抽象了我的单元测试套件,因为我可以将单元测试定义为文本文件中的行,如下所示:“ 1 + 2 = 3”,其中“ 3”是预期的结束显示,以及之前的所有内容按下哪个按钮。
奥利(Olie)2010年

那么您的操作方法是否没有(id)sender参数?您不能只调用该方法并将按钮作为发送者传递吗?
Jasarien

3
由于测试工具的抽象性质,我不知道需要为特定按钮调用的方法。我想我可以深入研究按钮并获得它,但是这样做sendActionsForControlEvents:为我完成所有这些工作,出错的机会更少,并且使测试抽象化并适合设计。
Olie

Answers:


459

原来是

[buttonObj sendActionsForControlEvents: UIControlEventTouchUpInside];

在这种情况下,完全满足了我的需求。

编辑:不要忘记在主线程中执行此操作,以获得与用户按下类似的结果。


对于Swift 3:

buttonObj.sendActions(for: .touchUpInside)


与致电没有什么不同[myController myActionMethod:myButton1];
Jasarien

11
您在评论回应中有很大的克制感;)
Dan Rosenstark 2010年

@Jasarien完全不同,因为它将触摸事件发送到所有注册的目标(侦听器)。
htafoya

2
不幸的是,这两种方法都不总是有效-它们依赖于接收者是UIControl,而不是例如具有轻击手势。
使用者

1
@ChenLiYong,一个原因是,如果myActionMethod:它不是公共的,那么您就不能直接调用它。
Iulian Onofrei

50

Swift的此答案的更新

buttonObj.sendActionsForControlEvents(.TouchUpInside)

编辑:为Swift 3更新

buttonObj.sendActions(for: .touchUpInside)

1
我会说:buttonObj.sendActionsForControlEvents(.TouchUpInside)甚至是Swift风格的;)
Sajjon

1
我不认为如果在不支持运行循环的情况下在XCTestCase中创建按钮将无法正常工作。
CopperCash18年

6

如果您想进行这种测试,那么您会喜欢iOS 4中的UI自动化支持。您可以编写JavaScript来轻松模拟按钮的按下等操作,尽管文档(尤其是入门部分)有点疏。


1
是的,这很酷,但是我想通过应用程序而不是通过Instruments(如果您是说这种方法)来完成它
Olie 2010年

仪器与您的应用一起运行。该应用仍在运行,Instruments仅模拟触摸。
杰夫·凯利

6
Jeff,我了解Instruments,我的意思是:我希望单元测试可以在口袋中的设备中运行,而无需手提电脑,XCode或Instruments。还是您知道在设备上运行乐器的秘密?;)
Olie

5

在这种情况下,UIButton是从派生的UIControl。这适用于衍生自的对象UIControl

我想UIBarButtonItem在特定的用例上重用动作。在这里,UIBarButtonItem不提供方法sendActionsForControlEvents:

但幸运的是,UIBarButtonItem具有针对目标和行动的属性。

 if(notHappy){        
         SEL exit = self.navigationItem.rightBarButtonItem.action;
         id  world = self.navigationItem.rightBarButtonItem.target;
         [world performSelector:exit];
 }

在这里rightBarButtonItem是类型UIBarButtonItem


如果使用UIBarButtonItem,则可以只使用[self doAction:self.navigationItem.rightBarButtonItem]; //-doAction:是self.navigationItem.rightBarButtonItem的切换动作名称。
13年


5

斯威夫特3:

self.btn.sendActions(for: .touchUpInside)

3
这只是重复得分较高的答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.