bagaimana cara memalsukan acara sentuh ke UIButton secara terprogram?

183

Saya sedang menulis beberapa tes unit dan, karena sifat aplikasi ini, penting bahwa saya mendapatkan setinggi UImungkin rantai. Jadi, apa yang ingin saya lakukan adalah secara terprogram memicu tombol-tekan, seolah-olah pengguna telah menekan tombol di GUI.

(Ya, ya - saya hanya bisa memanggil IBActionpemilih tetapi, sekali lagi, sifat aplikasi ini membuatnya penting bahwa saya memalsukan tombol yang sebenarnya, sehingga IBActiondipanggil dari tombol itu sendiri.)

Apa metode yang disukai untuk melakukan ini?

Olie
sumber
Bisakah Anda menjelaskan mengapa Anda memalsukan sentuhan tombol daripada memanggil metode tindakan secara langsung? Sebenarnya tidak ada perbedaan praktis.
Jasarien
1
@Jasarien: yah, karena ada perbedaan! ;) Di aplikasi saya, beberapa tombol menggunakan metode tindakan yang sama, dan metode ini mem-parsing bagaimana berperilaku berdasarkan tag tombol. Jadi unit test, selain menguji satu jalur kode tertentu melalui metode ini, (a) perlu menguji semuanya dan (b) juga memverifikasi bahwa tombol-tombol tersebut terhubung dengan benar. Selain itu, itu juga abstrak suite unit-test saya, karena saya dapat mendefinisikan tes unit sebagai baris dalam file teks dengan sesuatu seperti ini: "1 + 2 = 3" di mana "3" adalah tampilan akhir yang diharapkan, dan segala sesuatu sebelum itu adalah tombol mana yang harus ditekan.
Olie
juga tidakkah metode tindakan Anda memiliki parameter pengirim (id)? Tidak bisakah Anda memanggil metode itu dan meneruskan tombol sebagai pengirim?
Jasarien
3
Karena sifat abstrak dari test harness saya, saya tidak TAHU metode yang perlu dipanggil untuk tombol tertentu. Saya kira saya bisa menggali ke dalam tombol dan mendapatkannya, tetapi melakukan sendActionsForControlEvents: melakukan semua ini untuk saya, dengan lebih sedikit kesempatan untuk kesalahan, dan membuat abstrak tes dan sesuai dengan desain.
Olie

Jawaban:

459

Ternyata itu

[buttonObj sendActionsForControlEvents: UIControlEventTouchUpInside];

mendapatkan apa yang saya butuhkan, dalam hal ini.

Sunting: Jangan lupa melakukan ini di utas utama, untuk mendapatkan hasil yang mirip dengan pers pengguna.


Untuk Swift 3:

buttonObj.sendActions(for: .touchUpInside)

Olie
sumber
Yang tidak berbeda dengan menelepon[myController myActionMethod:myButton1];
Jasarien
11
Anda sangat menahan diri dalam tanggapan komentar Anda;)
Dan Rosenstark
@Jasarien sangat berbeda, karena akan mengirimkan acara sentuh ke semua target yang terdaftar (pendengar).
htafoya
2
Sayangnya, tak satu pun dari ini akan selalu bekerja - mereka bergantung pada penerima yang menjadi UIControl, daripada misalnya memiliki gerakan tap.
tooluser
1
@ChenLiYong, Salah satu alasannya adalah jika myActionMethod:tidak publik, dan Anda tidak dapat memanggilnya secara langsung.
Iulian Onofrei
50

Pembaruan untuk jawaban ini untuk Swift

buttonObj.sendActionsForControlEvents(.TouchUpInside)

EDIT : Diperbarui untuk Swift 3

buttonObj.sendActions(for: .touchUpInside)
Hellojeffy
sumber
1
Saya akan mengatakan bahwa: buttonObj.sendActionsForControlEvents (.TouchUpInside) bahkan lebih gaya Swift;)
Sajjon
1
Saya tidak berpikir ini akan berfungsi jika tombol dibuat dalam XCTestCase tanpa menjalankan loop yang mendukung.
CopperCash
6

Jika Anda ingin melakukan pengujian semacam ini, Anda akan menyukai dukungan UI Automation di iOS 4. Anda dapat menulis JavaScript untuk mensimulasikan penekanan tombol, dll. Cukup mudah, meskipun dokumentasi (terutama bagian yang memulai) sedikit jarang.

Jeff Kelley
sumber
1
Ya, itu hal-hal keren, tapi saya mencoba melakukannya dari dalam aplikasi, bukan melalui Instrumen (jika itu metode yang Anda maksud.)
Olie
Instrumen berjalan dengan aplikasi Anda. Aplikasi ini masih berjalan, Instrumen hanya mensimulasikan sentuhan.
Jeff Kelley
6
Saya mengerti Instruments, Jeff - apa yang saya katakan adalah: Saya ingin unit-tes saya berjalan di perangkat di saku saya, tanpa laptop atau XCode atau Instrumen yang berguna. Atau tahukah Anda rahasia menjalankan instrumen pada perangkat? ;)
Olie
6

Swift 3:

self.btn.sendActions(for: .touchUpInside)
Gobi M
sumber
3
Ini hanya mengulangi jawaban skor yang lebih tinggi.
Pang
5

Dalam hal ini, UIButtonberasal dari UIControl. Ini berfungsi untuk objek yang berasal UIControl.

Saya ingin menggunakan kembali UIBarButtonItemtindakan " " pada kasus penggunaan khusus. Di sini, UIBarButtonItemtidak menawarkan metodesendActionsForControlEvents:

Tetapi untungnya, UIBarButtonItemmemiliki sifat untuk target & tindakan.

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

Di sini, rightBarButtonItemadalah tipe UIBarButtonItem.

Hitesh Savaliya
sumber
jika Anda menggunakan UIBarButtonItem, Anda bisa [self doAction: self.navigationItem.rightBarButtonItem]; // - doAction: adalah nama tindakan beralih self.navigationItem.rightBarButtonItem.
mulai
5

Untuk Xamarin iOS

btnObj.SendActionForControlEvents(UIControlEvent.TouchUpInside);

Referensi

Durai Amuthan.H
sumber
-3

Swift 4:

diri Anda. Tombol (diri)

ELEMENTO Seni
sumber