Atualização: eu estava errado. Você pode usar UIApplication.shared.sendAction(_:to:from:for:)
o primeiro respondedor demonstrado neste link: http://stackoverflow.com/a/14135456/746890 .
A maioria das respostas aqui não consegue encontrar o primeiro respondente atual, se ele não estiver na hierarquia de visualizações. Por exemplo, AppDelegate
ou UIViewController
subclasses.
Existe uma maneira de garantir que você o encontre, mesmo que o primeiro objeto de resposta não seja a UIView
.
Primeiro vamos implementar uma versão invertida, usando a next
propriedade de UIResponder
:
extension UIResponder {
var nextFirstResponder: UIResponder? {
return isFirstResponder ? self : next?.nextFirstResponder
}
}
Com essa propriedade computada, podemos encontrar o primeiro atendedor atual de baixo para cima, mesmo que não seja UIView
. Por exemplo, de um view
para oUIViewController
quem está gerenciando, se o controlador de exibição for o primeiro a responder.
No entanto, ainda precisamos de uma resolução de cima para baixo, uma única var
para obter o primeiro atendedor atual.
Primeiro com a hierarquia de visualizações:
extension UIView {
var previousFirstResponder: UIResponder? {
return nextFirstResponder ?? subviews.compactMap { $0.previousFirstResponder }.first
}
}
Isso procurará o primeiro respondente de trás para frente e, se não o encontrasse, instruiria suas sub-visualizações a fazer a mesma coisa (porque as sub-visualizações next
não são necessariamente elas mesmas ). Com isso, podemos encontrá-lo de qualquer ponto de vista, inclusive UIWindow
.
E, finalmente, podemos construir isso:
extension UIResponder {
static var first: UIResponder? {
return UIApplication.shared.windows.compactMap({ $0.previousFirstResponder }).first
}
}
Portanto, quando você deseja recuperar a primeira resposta, pode ligar para:
let firstResponder = UIResponder.first