Відповідь Зева Айзенберга проста і зрозуміла, але це не завжди працює, і може не вдатися до цього попереджувального повідомлення:
Warning: Attempt to present <UIAlertController: 0x7fe6fd951e10>
on <ThisViewController: 0x7fe6fb409480> which is already presenting
<AnotherViewController: 0x7fe6fd109c00>
Це відбувається тому, що Windows rootViewController не знаходиться вгорі представлених представлень. Щоб виправити це, нам потрібно пройти ланцюжок презентацій, як показано в моєму коді розширення UIAlertController, написаному на 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)
}
Оновлення 15.09.2017:
Випробувано та підтверджено, що вищезазначена логіка як і раніше чудово працює в нещодавно доступному насінні iOS 11 GM. Однак метод голосування, проведений методом спритності, не робить: огляд попередження, представлений у щойно відрізаномуUIWindow
знаходиться нижче клавіатури і, можливо, не дозволяє користувачеві натискати його кнопки. Це тому, що в iOS 11 всі windowLevels вище, ніж у вікні клавіатури, опускаються до рівня нижче нього.
Одним з артефактів подання від keyWindow
хоча є анімація розсуву клавіатури вниз, коли подано попередження, і сповзання вгору, коли попередження відхиляється. Якщо ви хочете, щоб клавіатура залишалася там під час презентації, ви можете спробувати представити її у верхньому вікні, як показано нижче в коді:
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
}
}
}
Єдиною не настільки великою частиною вищевказаного коду є те, що він перевіряє ім'я класу, UIRemoteKeyboardWindow
щоб переконатися, що ми можемо також включити його. Тим не менш, наведений вище код чудово працює в iOS 9, 10 і 11 GM насінні, з правильним кольором відтінку і без розсувних артефактів клавіатури.