Aggiornamento: ho sbagliato. Puoi infatti utilizzare UIApplication.shared.sendAction(_:to:from:for:)
per chiamare il primo risponditore dimostrato in questo link: http://stackoverflow.com/a/14135456/746890 .
La maggior parte delle risposte qui non riesce davvero a trovare l'attuale primo risponditore se non si trova nella gerarchia della vista. Ad esempio, AppDelegate
o UIViewController
sottoclassi.
C'è un modo per garantirti di trovarlo anche se il primo oggetto responder non è un UIView
.
Innanzitutto, consente di implementarne una versione inversa, usando la next
proprietà di UIResponder
:
extension UIResponder {
var nextFirstResponder: UIResponder? {
return isFirstResponder ? self : next?.nextFirstResponder
}
}
Con questa proprietà calcolata, possiamo trovare l'attuale primo risponditore dal basso verso l'alto anche se non lo è UIView
. Ad esempio, da a view
aUIViewController
chi lo sta gestendo, se il controller di visualizzazione è il primo risponditore.
Tuttavia, abbiamo ancora bisogno di una risoluzione dall'alto verso il basso, una sola var
per ottenere l'attuale primo risponditore.
Innanzitutto con la gerarchia delle viste:
extension UIView {
var previousFirstResponder: UIResponder? {
return nextFirstResponder ?? subviews.compactMap { $0.previousFirstResponder }.first
}
}
Questo cercherà il primo risponditore all'indietro e, se non riuscisse a trovarlo, direbbe ai suoi sottoview di fare la stessa cosa (perché il suo sottoview next
non è necessariamente se stesso). Con questo possiamo trovarlo da qualsiasi vista, incluso UIWindow
.
E infine, possiamo costruire questo:
extension UIResponder {
static var first: UIResponder? {
return UIApplication.shared.windows.compactMap({ $0.previousFirstResponder }).first
}
}
Quindi, quando si desidera recuperare il primo risponditore, è possibile chiamare:
let firstResponder = UIResponder.first