Ios 如何以编程方式将触摸事件伪造为UIButton?
我正在编写一些单元测试,由于这个特定应用程序的性质,我必须尽可能地在Ios 如何以编程方式将触摸事件伪造为UIButton?,ios,iphone,uibutton,touch-event,Ios,Iphone,Uibutton,Touch Event,我正在编写一些单元测试,由于这个特定应用程序的性质,我必须尽可能地在UI链中占据较高的位置。因此,我想做的是通过编程触发按钮按下,就像用户在GUI中按下按钮一样 (是的,是的——我可以直接调用iAction选择器,但同样,这个特定应用程序的性质使得我必须假装实际按下按钮,以便从按钮本身调用iAction。) 做这件事的首选方法是什么?如果你想做这种测试,你会喜欢iOS 4中的UI自动化支持。您可以编写JavaScript来模拟按钮按下等操作,尽管文档(尤其是入门部分)有点稀疏。事实证明 [按钮发
UI
链中占据较高的位置。因此,我想做的是通过编程触发按钮按下,就像用户在GUI
中按下按钮一样
(是的,是的——我可以直接调用iAction
选择器,但同样,这个特定应用程序的性质使得我必须假装实际按下按钮,以便从按钮本身调用iAction
。)
做这件事的首选方法是什么?如果你想做这种测试,你会喜欢iOS 4中的UI自动化支持。您可以编写JavaScript来模拟按钮按下等操作,尽管文档(尤其是入门部分)有点稀疏。事实证明
[按钮发送控制事件的操作:UIControlEventTouchUpInside];
在这种情况下,我得到了我所需要的
编辑:不要忘记在主线程中执行此操作,以获得类似于用户按键的结果
对于Swift 3:
buttonObj.sendActions(用于:.touchUpInside)
在这种情况下,UIButton
源自UIControl
。这适用于源自UIControl
的对象
我想在特定用例上重用“uibarbuttonim
”操作。在这里,UIBarButtonItem
不提供方法sendActionsForControlEvents:
但幸运的是,uibarbuttoneim
具有target和action属性
if(notHappy){
SEL exit = self.navigationItem.rightBarButtonItem.action;
id world = self.navigationItem.rightBarButtonItem.target;
[world performSelector:exit];
}
这里,
rightBarButtonItem
属于UIBarButtonItem
对Swift回答的更新
buttonObj.sendActionsForControlEvents(.TouchUpInside)
编辑:为Swift 3更新
buttonObj.sendActions(for: .touchUpInside)
对于Xamarin iOS
btnObj.SendActionForControlEvents(UIControlEvent.TouchUpInside);
Swift 3:
self.btn.sendActions(for: .touchUpInside)
Swift 4:
self.yourButton(self)对于编写没有UI测试的单元测试的人来说非常方便;-) Swift为
UIBarButtonItem
提供了5种解决方法,它没有像UIButton等sendAction
方法
extension UIBarButtonItem {
func sendAction() {
guard let myTarget = target else { return }
guard let myAction = action else { return }
let control: UIControl = UIControl()
control.sendAction(myAction, to: myTarget, for: nil)
}
}
现在你可以简单地:
let action = UIBarButtonItem(title: "title", style: .done, target: self, action: #selector(doSomething))
action.sendAction()
Swift 5:
class ViewController: UIViewController {
@IBOutlet weak var theTextfield: UITextField!
@IBOutlet weak var someButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
theTextfield.text = "Pwd"
someButton.sendActions(for: .touchUpInside)
}
@IBAction func someButtonTap(_ sender: UIButton) {
print("button tapped")
}
}
你能解释一下为什么假装触摸按钮比直接调用动作方法更重要吗?实际上并没有什么区别。@Jasarien:因为有区别在我的应用程序中,几个按钮使用相同的动作方法,该方法根据按钮的标记解析行为。因此,单元测试除了通过该方法测试一个特定的代码路径外,(a)还需要测试所有的代码路径,(b)还验证按钮是否正确连接。此外,它很好地抽象了我的单元测试套件,因为我可以在文本文件中将单元测试定义为这样的行:“1+2=3”,其中“3”是预期的结束显示,而之前的所有内容都是要按下哪个按钮。那么,您的操作方法没有(id)sender参数吗?你就不能调用这个方法并将按钮作为发送者传递吗?因为我的测试工具的抽象性质,我不知道需要为特定的按钮调用什么方法。我想我可以挖掘按钮并获得它,但执行sendActionsForControlEvents:这一切都是为了我,错误的机会更少,并保持测试抽象和符合设计。是的,这是很酷的东西,但我尝试从应用程序内部执行,而不是通过仪器(如果你指的是这种方法的话)仪器与你的应用程序一起运行。应用程序还在运行,仪器只是模拟触摸。我理解仪器,杰夫——我想说的是:我希望我的单元测试在口袋里的设备中运行,而不需要笔记本电脑、XCode或仪器。或者你知道在设备上运行仪器的秘密吗?;)这与调用
[myController myActionMethod:myButton1]没有什么不同代码>您在评论回复中有很大的限制;)不幸的是,这两种方法都不总是有效的-它们依赖于接收者是一个UIControl,而不是一个点击手势。@ChenLiYong,一个原因是如果myActionMethod:
不是公共的,所以你不能直接调用它。Xamarin:buttonObj.SendActionForControlEvents(UIControlEvent.TouchUpInside)代码>如果您使用uiBarButtonim,您可以只使用[self-doAction:self.navigationItem.RightBarButtonim]//-doAction:是self.navigationItem.RightBarButtonim的切换操作名称。我想说的是:buttonObj.sendActionsForControlEvents(.TouchUpInside)更为快速;)如果按钮是在没有运行循环支持的XCTestCase中创建的,我认为这是行不通的。这只是重复得分较高的答案。