Cập nhật: Tôi đã sai. Bạn thực sự có thể sử dụng UIApplication.shared.sendAction(_:to:from:for:)
để gọi phản hồi đầu tiên được thể hiện trong liên kết này: http://stackoverflow.com/a/14135456/746890 .
Hầu hết các câu trả lời ở đây thực sự không thể tìm thấy phản hồi đầu tiên hiện tại nếu nó không nằm trong hệ thống phân cấp chế độ xem. Ví dụ, AppDelegate
hoặc các UIViewController
lớp con.
Có một cách để đảm bảo bạn tìm thấy nó ngay cả khi đối tượng phản hồi đầu tiên không phải là a UIView
.
Trước tiên, hãy thực hiện phiên bản đảo ngược của nó, sử dụng thuộc next
tính của UIResponder
:
extension UIResponder {
var nextFirstResponder: UIResponder? {
return isFirstResponder ? self : next?.nextFirstResponder
}
}
Với thuộc tính được tính toán này, chúng ta có thể tìm thấy phản hồi đầu tiên hiện tại từ dưới lên trên ngay cả khi nó không UIView
. Ví dụ: từ a view
đếnUIViewController
ai đang quản lý nó, nếu bộ điều khiển xem là trả lời đầu tiên.
Tuy nhiên, chúng ta vẫn cần một độ phân giải từ trên xuống, một var
để có được phản hồi đầu tiên hiện tại.
Đầu tiên với hệ thống phân cấp xem:
extension UIView {
var previousFirstResponder: UIResponder? {
return nextFirstResponder ?? subviews.compactMap { $0.previousFirstResponder }.first
}
}
Điều này sẽ tìm kiếm phản hồi đầu tiên ngược và nếu không thể tìm thấy nó, nó sẽ bảo các cuộc phỏng vấn của nó làm điều tương tự (bởi vì cuộc phỏng vấn của nó next
nó không nhất thiết phải là chính nó). Với điều này, chúng tôi có thể tìm thấy nó từ bất kỳ xem, bao gồm cả UIWindow
.
Và cuối cùng, chúng ta có thể xây dựng điều này:
extension UIResponder {
static var first: UIResponder? {
return UIApplication.shared.windows.compactMap({ $0.previousFirstResponder }).first
}
}
Vì vậy, khi bạn muốn truy xuất phản hồi đầu tiên, bạn có thể gọi:
let firstResponder = UIResponder.first