Оновлення: я помилявся. Ви дійсно можете використовувати UIApplication.shared.sendAction(_:to:from:for:)
для виклику першого відповідача, продемонстрованого за цим посиланням: http://stackoverflow.com/a/14135456/746890 .
Більшість відповідей тут насправді не можуть знайти поточного першого відповіді, якщо він не знаходиться в ієрархії перегляду. Наприклад, AppDelegate
або UIViewController
підкласи.
Існує спосіб гарантувати вам його знайти, навіть якщо об'єктом першого відповіді не є UIView
.
Спочатку давайте реалізувати зворотну версію її, використовуючи next
властивість UIResponder
:
extension UIResponder {
var nextFirstResponder: UIResponder? {
return isFirstResponder ? self : next?.nextFirstResponder
}
}
За допомогою цього обчисленого властивості ми можемо знайти поточного першого відповіді знизу вгору, навіть якщо його немає UIView
. Наприклад, від a view
до theUIViewController
хто ним керує, якщо контролер перегляду є першим відповіддю.
Однак нам все ще потрібна роздільна здатність зверху вниз, одинарна, var
щоб отримати поточний перший відповідь.
Спочатку з ієрархією перегляду:
extension UIView {
var previousFirstResponder: UIResponder? {
return nextFirstResponder ?? subviews.compactMap { $0.previousFirstResponder }.first
}
}
Це буде шукати першого відповіді заднім числом, і якщо він не зміг його знайти, він сказав би своїм підвідділам зробити те ж саме (тому що його підрозділ next
необов'язково сам). Завдяки цьому ми можемо знайти його з будь-якого погляду, в тому числі UIWindow
.
І нарешті, ми можемо побудувати це:
extension UIResponder {
static var first: UIResponder? {
return UIApplication.shared.windows.compactMap({ $0.previousFirstResponder }).first
}
}
Отже, коли ви хочете отримати першого відповіді, ви можете зателефонувати:
let firstResponder = UIResponder.first