La réponse de Zev Eisenberg est simple et directe, mais elle ne fonctionne pas toujours, et elle peut échouer avec ce message d'avertissement:
Warning: Attempt to present <UIAlertController: 0x7fe6fd951e10>
on <ThisViewController: 0x7fe6fb409480> which is already presenting
<AnotherViewController: 0x7fe6fd109c00>
Cela est dû au fait que le rootViewController Windows n'est pas en haut des vues présentées. Pour corriger cela, nous devons remonter la chaîne de présentation, comme indiqué dans mon code d'extension UIAlertController écrit dans Swift 3:
/// show the alert in a view controller if specified; otherwise show from window's root pree
func show(inViewController: UIViewController?) {
if let vc = inViewController {
vc.present(self, animated: true, completion: nil)
} else {
// find the root, then walk up the chain
var viewController = UIApplication.shared.keyWindow?.rootViewController
var presentedVC = viewController?.presentedViewController
while presentedVC != nil {
viewController = presentedVC
presentedVC = viewController?.presentedViewController
}
// now we present
viewController?.present(self, animated: true, completion: nil)
}
}
func show() {
show(inViewController: nil)
}
Mises à jour le 15/09/2017:
Testé et confirmé que la logique ci-dessus fonctionne toujours très bien dans la nouvelle graine iOS 11 GM. Cependant, la méthode la plus votée par agilityvision ne le fait pas: la vue d'alerte présentée dans une nouvelle version UIWindow
est en dessous du clavier et empêche potentiellement l'utilisateur d'appuyer sur ses boutons. En effet, dans iOS 11, tous les niveaux de fenêtre supérieurs à ceux de la fenêtre du clavier sont abaissés à un niveau inférieur.
Un des artefacts de la présentation keyWindow
est cependant l'animation du clavier glissant vers le bas lorsque l'alerte est présentée et remontant lorsque l'alerte est rejetée. Si vous souhaitez que le clavier y reste pendant la présentation, vous pouvez essayer de présenter à partir de la fenêtre supérieure elle-même, comme indiqué dans le code ci-dessous:
func show(inViewController: UIViewController?) {
if let vc = inViewController {
vc.present(self, animated: true, completion: nil)
} else {
// get a "solid" window with the highest level
let alertWindow = UIApplication.shared.windows.filter { $0.tintColor != nil || $0.className() == "UIRemoteKeyboardWindow" }.sorted(by: { (w1, w2) -> Bool in
return w1.windowLevel < w2.windowLevel
}).last
// save the top window's tint color
let savedTintColor = alertWindow?.tintColor
alertWindow?.tintColor = UIApplication.shared.keyWindow?.tintColor
// walk up the presentation tree
var viewController = alertWindow?.rootViewController
while viewController?.presentedViewController != nil {
viewController = viewController?.presentedViewController
}
viewController?.present(self, animated: true, completion: nil)
// restore the top window's tint color
if let tintColor = savedTintColor {
alertWindow?.tintColor = tintColor
}
}
}
La seule partie moins importante du code ci-dessus est qu'il vérifie le nom UIRemoteKeyboardWindow
de la classe pour s'assurer que nous pouvons également l'inclure. Néanmoins, le code ci-dessus fonctionne très bien dans les semences GM iOS 9, 10 et 11, avec la bonne teinte et sans les artefacts coulissants du clavier.