Actualización: estaba equivocado. De hecho, puede usar UIApplication.shared.sendAction(_:to:from:for:)
para llamar al primer respondedor demostrado en este enlace: http://stackoverflow.com/a/14135456/746890 .
La mayoría de las respuestas aquí realmente no pueden encontrar el primer respondedor actual si no está en la jerarquía de vistas. Por ejemplo, AppDelegate
o UIViewController
subclases.
Hay una manera de garantizar que lo encuentre incluso si el primer objeto de respuesta no es un UIView
.
Primero implementemos una versión inversa de la misma, usando la next
propiedad de UIResponder
:
extension UIResponder {
var nextFirstResponder: UIResponder? {
return isFirstResponder ? self : next?.nextFirstResponder
}
}
Con esta propiedad calculada, podemos encontrar el primer respondedor actual de abajo hacia arriba, incluso si no lo es UIView
. Por ejemplo, de a view
a laUIViewController
quién lo administra, si el controlador de vista es el primer respondedor.
Sin embargo, todavía necesitamos una resolución de arriba hacia abajo, una sola var
para obtener el primer respondedor actual.
Primero con la jerarquía de vistas:
extension UIView {
var previousFirstResponder: UIResponder? {
return nextFirstResponder ?? subviews.compactMap { $0.previousFirstResponder }.first
}
}
Esto buscará el primer respondedor al revés, y si no puede encontrarlo, le dirá a sus subvistas que hagan lo mismo (porque su subvista next
no es necesariamente ella misma). Con esto podemos encontrarlo desde cualquier punto de vista, incluido UIWindow
.
Y finalmente, podemos construir esto:
extension UIResponder {
static var first: UIResponder? {
return UIApplication.shared.windows.compactMap({ $0.previousFirstResponder }).first
}
}
Entonces, cuando desee recuperar el primer respondedor, puede llamar a:
let firstResponder = UIResponder.first