Làm thế nào để lập trình giả một sự kiện chạm vào UIButton?


183

Tôi đang viết một số bài kiểm tra đơn vị và, vì bản chất của ứng dụng cụ thể này, điều quan trọng là tôi phải tăng UIchuỗi càng cao càng tốt. Vì vậy, những gì tôi muốn làm là lập trình kích hoạt một lần nhấn nút, như thể người dùng đã nhấn nút trong GUI.

(Vâng, vâng - Tôi chỉ có thể gọi IBActionbộ chọn nhưng, một lần nữa, bản chất của ứng dụng cụ thể này khiến tôi giả mạo nhấn nút thực tế, sao cho chính nó IBActionđược gọi từ nút.)

Phương pháp ưa thích để làm điều này là gì?


Bạn có thể giải thích tại sao điều quan trọng là bạn giả mạo nút chạm chứ không gọi trực tiếp phương thức hành động? Thực sự không có sự khác biệt thực tế.
Jasarien

1
@Jasarien: tốt, bởi vì có một sự khác biệt! ;) Trong ứng dụng của tôi, một số nút sử dụng cùng một phương thức hành động và phương thức phân tích cú pháp cách ứng xử dựa trên thẻ của nút. Vì vậy, kiểm tra đơn vị, ngoài việc kiểm tra một đường dẫn mã cụ thể thông qua phương thức, (a) cần kiểm tra tất cả chúng và (b) cũng xác minh rằng các nút được nối dây chính xác. Ngoài ra, nó trừu tượng hóa bộ công cụ kiểm tra đơn vị của tôi, vì tôi có thể định nghĩa các kiểm tra đơn vị là các dòng trong tệp văn bản với nội dung như sau: "1 + 2 = 3" trong đó "3" là màn hình kết thúc dự kiến ​​và mọi thứ trước nó là nút nào để đẩy.
Olie

cũng không phương thức hành động của bạn có một tham số người gửi (id)? Bạn không thể gọi phương thức và chuyển nút là người gửi sao?
Jasarien

3
Do tính chất trừu tượng của khai thác thử nghiệm của tôi, tôi không BIẾT phương pháp cần được gọi cho một nút cụ thể. Tôi cho rằng tôi có thể đào sâu vào nút và lấy nó, nhưng thực hiện sendActionsForControlEvents: thực hiện tất cả điều này cho tôi, với ít cơ hội hơn cho lỗi và giữ cho bài kiểm tra trừu tượng và phù hợp với thiết kế.
Olie

Câu trả lời:


459

Hóa ra

[buttonObj sendActionsForControlEvents: UIControlEventTouchUpInside];

đã cho tôi chính xác những gì tôi cần, trong trường hợp này.

EDIT: Đừng quên làm điều này trong luồng chính, để có kết quả tương tự như báo chí người dùng.


Dành cho Swift 3:

buttonObj.sendActions(for: .touchUpInside)


Điều này không khác gì gọi[myController myActionMethod:myButton1];
Jasarien

11
bạn có sự kiềm chế tuyệt vời trong các phản hồi bình luận của mình;)
Dan Rosenstark

@Jasarien khá khác biệt, vì nó sẽ gửi sự kiện chạm tới tất cả các mục tiêu đã đăng ký (người nghe).
htafoya

2
Thật không may, cả hai điều này sẽ không luôn hoạt động - họ dựa vào người nhận là một UIControl, thay vì có một cử chỉ nhấn.
cụ

1
@ChenLiYong, Một lý do sẽ là nếu myActionMethod:không công khai và vì vậy bạn không thể gọi trực tiếp.
Iulian Onofrei 22/03/2016

50

Một bản cập nhật cho câu trả lời này cho Swift

buttonObj.sendActionsForControlEvents(.TouchUpInside)

EDIT : Cập nhật cho Swift 3

buttonObj.sendActions(for: .touchUpInside)

1
Tôi sẽ nói rằng: buttonObj.sendActionsForControlEvents (.TouchUpInside) thậm chí còn theo phong cách Swift hơn;)
Sajjon 19/2/2016

1
Tôi không nghĩ rằng nó sẽ hoạt động nếu nút được tạo trong XCTestCase mà không có vòng lặp chạy hỗ trợ.
CopperCash

6

Nếu bạn muốn thực hiện loại thử nghiệm này, bạn sẽ thích hỗ trợ Tự động hóa giao diện người dùng trong iOS 4. Bạn có thể viết JavaScript để mô phỏng các lần nhấn nút, v.v ... khá dễ dàng, mặc dù tài liệu (đặc biệt là phần bắt đầu) là một chút thưa thớt.


1
Vâng, đó là thứ tuyệt vời, nhưng tôi đang cố gắng thực hiện nó từ trong ứng dụng, không phải thông qua Dụng cụ (nếu đó là phương pháp mà bạn muốn nói.)
Olie

Dụng cụ chạy với ứng dụng của bạn. Ứng dụng vẫn đang chạy, Dụng cụ chỉ mô phỏng cảm ứng.
Jeff Kelley

6
Tôi hiểu dụng cụ, Jeff - điều tôi đang nói là: Tôi muốn các bài kiểm tra đơn vị của mình chạy trong thiết bị trong túi của mình, không có máy tính xách tay hoặc XCode hoặc Dụng cụ tiện dụng. Hay bạn có biết bí mật của các thiết bị chạy trên thiết bị? ;)
Olie

5

Trong trường hợp này, UIButtoncó nguồn gốc từ UIControl. Điều này làm việc cho các đối tượng có nguồn gốc từ UIControl.

Tôi muốn sử dụng lại " UIBarButtonItem" hành động trong trường hợp sử dụng cụ thể. Ở đây, UIBarButtonItemkhông cung cấp phương phápsendActionsForControlEvents:

Nhưng may mắn, UIBarButtonItemcó tài sản cho mục tiêu và hành động.

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

Đây rightBarButtonItemlà loại UIBarButtonItem.


nếu bạn sử dụng UIBarButtonItem, bạn chỉ có thể [self doAction: self.navlationItem.rightBarButtonItem]; // - doAction: là self.navlationItem.rightBarButtonItem là tên hành động chuyển đổi.
c0ming


5

Swift 3:

self.btn.sendActions(for: .touchUpInside)

3
Đây chỉ là lặp lại các câu trả lời điểm cao hơn.
Pang

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.