як програмно підробити подію на дотик до UIButton?


183

Я пишу кілька одиничних тестів і, зважаючи на характер цього конкретного додатку, важливо, щоб я піднявся якомога вище в UIланцюжку. Отже, те, що я хотів би зробити, це програмно запустити натискання кнопки, як ніби користувач натиснув кнопку в GUI.

(Так, так - я міг би просто зателефонувати IBActionселектору, але, знову ж таки, характер цього конкретного додатку робить важливим, щоб я підробляв фактичне натискання кнопки, таким чином, щоб дзвонити саме IBActionз кнопки.)

Який бажаний спосіб зробити це?


Чи можете ви пояснити, чому важливо підробити натискання кнопки, а не викликати метод дії безпосередньо? Практично різниці немає.
Jasarien

1
@Jasarien: ну, бо є різниця! ;) У моєму додатку кілька кнопок використовують один і той же спосіб дії, і метод аналізує, як поводитись, ґрунтуючись на тезі кнопки. Таким чином, блок перевірки, окрім тестування одного конкретного кодового шляху шляхом методу, (а) потребує тестування їх усіх і (б) також перевірки правильності підключення кнопок. Крім того, він чудово резюмує мій блок-тестовий набір, оскільки я можу визначити одиничні тести як рядки в текстовому файлі приблизно так: "1 + 2 = 3", де "3" - очікуване кінцеве відображення, і все до нього це яку кнопку натиснути.
Олі

добре, чи не має у вашому способі дії параметр (id) відправника? Ви не можете просто зателефонувати за методом і передати кнопку як відправник?
Jasarien

3
Через абстрактний характер мого тест-ременя я не знаю методу, який потрібно викликати для певної кнопки. Я гадаю, що я міг би заглибитись у кнопку та отримати її, але роблю sendActionsForControlEvents: чи все це для мене, з меншими можливостями для помилок, і зберігає тест абстрактно та відповідає дизайну.
Олі

Відповіді:


459

Виявляється, що

[buttonObj sendActionsForControlEvents: UIControlEventTouchUpInside];

отримав мені саме те, що мені потрібно, в даному випадку.

Редагувати: Не забудьте зробити це в основній темі, щоб отримати результати, подібні до натискання користувача.


Для Swift 3:

buttonObj.sendActions(for: .touchUpInside)


Що не відрізняється від дзвінка[myController myActionMethod:myButton1];
Jasarien

11
у вас є велика стриманість у ваших відповідях на коментарі;)
Dan Rosenstark

@Jasarien зовсім інший, оскільки він надсилатиме сенсорну подію всім зареєстрованим цілям (слухачам).
хтафоя

2
На жаль, жодне з них не працюватиме завжди - вони покладаються на те, що приймач буде UIControl, а не, наприклад, маючи жест натискання.
інструменткористувача

1
@ChenLiYong, Однією з причин було б, якщо цей файл myActionMethod:не є загальнодоступним, і тому ви не можете його безпосередньо зателефонувати.
Юліан Онофрей

50

Оновлення цієї відповіді для Swift

buttonObj.sendActionsForControlEvents(.TouchUpInside)

EDIT : оновлено для Swift 3

buttonObj.sendActions(for: .touchUpInside)

1
Я б сказав, що: buttonObj.sendActionsForControlEvents (.TouchUpInside) є ще більшим стилем Swift;)
Саджон

1
Я не думаю, що це спрацює, якщо кнопка створена в XCTestCase без підтримки циклу запуску.
CopperCash

6

Якщо ви хочете зробити таке тестування, вам сподобається підтримка UI Automation в iOS 4. Ви можете написати JavaScript, щоб імітувати натискання кнопок і т. Д. Досить легко, хоча документація (особливо частина, що починається) трохи розріджений


1
Так, це класні речі, але я намагаюсь робити це з програми, а не через інструменти (якщо це ви маєте на увазі метод.)
Олі,

Інструменти працює з вашим додатком. Додаток все ще працює, Інструменти просто імітує дотик.
Джефф Келлі

6
Я розумію, інструменти, Джефф, про що я говорю: я хочу, щоб мої одиничні тести працювали в пристрої в моїй кишені, без зручності ноутбука або XCode або інструментів. Або ви знаєте секрет запуску інструментів на пристрої? ;)
Олі

6

Швидкий 3:

self.btn.sendActions(for: .touchUpInside)

3
Це лише повторення вище набраних відповідей.
Панг

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.
c0ming


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.