¿Cómo simular mediante programación un evento táctil en un UIButton?


183

Estoy escribiendo algunas pruebas unitarias y, debido a la naturaleza de esta aplicación en particular, es importante que llegue lo más alto posible en la UIcadena. Entonces, lo que me gustaría hacer es activar programáticamente la presión de un botón, como si el usuario hubiera presionado el botón en el GUI.

(Sí, sí, podría llamar al IBActionselector, pero, una vez más, la naturaleza de esta aplicación en particular hace que sea importante falsificar la presión del botón real, de modo que IBActionse llame desde el botón mismo).

¿Cuál es el método preferido para hacer esto?


¿Podría explicar por qué es importante falsificar el toque del botón en lugar de llamar directamente al método de acción? Realmente no hay diferencia práctica.
Jasarien

1
@Jasarien: bueno, ¡porque hay una diferencia! ;) En mi aplicación, varios botones usan el mismo método de acción, y el método analiza cómo comportarse según la etiqueta del botón. Por lo tanto, la prueba unitaria, además de probar una ruta de código particular a través del método, (a) necesita probarlas todas y (b) también verifica que los botones estén conectados correctamente. Además, abstrae muy bien mi conjunto de pruebas unitarias, ya que puedo definir las pruebas unitarias como líneas en un archivo de texto con algo como esto: "1 + 2 = 3" donde "3" es la visualización final esperada, y todo lo que está antes. es qué botón presionar.
Olie

bueno, ¿su método de acción no tiene un parámetro de remitente (id)? ¿No podría simplemente llamar al método y pasar el botón como remitente?
Jasarien

3
Debido a la naturaleza abstracta de mi instrumento de prueba, no el método que tiene que ser llamado por un botón en particular. Supongo que podría profundizar en el botón y obtenerlo, pero hacer sendActionsForControlEvents: hace todo esto por mí, con menos oportunidades de error, y mantiene el resumen de la prueba y el diseño.
Olie

Respuestas:


459

Resulta que

[buttonObj sendActionsForControlEvents: UIControlEventTouchUpInside];

me consiguió exactamente lo que necesitaba, en este caso.

EDITAR: No olvide hacer esto en el hilo principal, para obtener resultados similares a los de una prensa de usuario.


Para Swift 3:

buttonObj.sendActions(for: .touchUpInside)


Lo que no es diferente a llamar[myController myActionMethod:myButton1];
Jasarien

11
tienes una gran moderación en tus comentarios;)
Dan Rosenstark

@Jasarien es bastante diferente, ya que enviará el evento táctil a todos los objetivos registrados (oyentes).
htafoya

2
Desafortunadamente, ninguno de estos siempre funcionará: confían en que el receptor sea un UIControl, en lugar de, por ejemplo, tener un gesto de toque.
tooluser

1
@ChenLiYong, una razón sería si el myActionMethod:no es público, por lo que no puede llamarlo directamente.
Iulian Onofrei

50

Una actualización de esta respuesta para Swift

buttonObj.sendActionsForControlEvents(.TouchUpInside)

EDITAR : actualizado para Swift 3

buttonObj.sendActions(for: .touchUpInside)

1
Yo diría que: buttonObj.sendActionsForControlEvents (.TouchUpInside) es aún más estilo Swift;)
Sajjon

1
No creo que esto funcione si el botón se crea en un XCTestCase sin un ciclo de ejecución compatible.
CopperCash

6

Si desea hacer este tipo de pruebas, le encantará el soporte de Automatización de la interfaz de usuario en iOS 4. Puede escribir JavaScript para simular presionar botones, etc. con bastante facilidad, aunque la documentación (especialmente la parte de inicio) es un poco escaso.


1
Sí, eso es genial, pero estoy tratando de hacerlo desde la aplicación, no a través de instrumentos (si ese es el método al que te refieres).
Olie

Instrumentos se ejecuta con su aplicación. La aplicación aún se está ejecutando, Instruments simplemente simula el tacto.
Jeff Kelley

66
Entiendo los instrumentos, Jeff, lo que digo es: quiero que mis pruebas unitarias se ejecuten en el dispositivo en mi bolsillo, sin una computadora portátil o XCode o Instruments a mano. ¿O conoces el secreto de ejecutar instrumentos en el dispositivo? ;)
Olie

6

Swift 3:

self.btn.sendActions(for: .touchUpInside)

3
Esto es solo repetir las respuestas mejor calificadas.
Pang

5

En este caso, UIButtonse deriva de UIControl. Esto funciona para objetos derivados de UIControl.

Quería reutilizar " UIBarButtonItem" la acción en un caso de uso específico. Aquí, UIBarButtonItemno ofrece métodosendActionsForControlEvents:

Pero afortunadamente, UIBarButtonItemtiene propiedades para el objetivo y la acción.

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

Aquí, rightBarButtonItemes de tipo UIBarButtonItem.


si usa UIBarButtonItem, puede simplemente [self doAction: self.navigationItem.rightBarButtonItem]; // - doAction: es el nombre de acción de alternar self.navigationItem.rightBarButtonItem.
llega el


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.