Zev Eisenberg'in cevabı basit ve basittir, ancak her zaman işe yaramaz ve bu uyarı mesajıyla başarısız olabilir:
Warning: Attempt to present <UIAlertController: 0x7fe6fd951e10>
on <ThisViewController: 0x7fe6fb409480> which is already presenting
<AnotherViewController: 0x7fe6fd109c00>
Bunun nedeni, windows rootViewController'ın sunulan görünümlerin üstünde olmamasıdır. Bunu düzeltmek için Swift 3'te yazılmış UIAlertController uzantı kodumda gösterildiği gibi sunum zincirine geçmeliyiz:
/// 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 ile ilgili güncellemeler:
Yukarıdaki mantığın yeni mevcut iOS 11 GM tohumunda hala harika çalıştığını test etti ve onayladı. Bununla birlikte, çeviklik tarafından en çok oylanan yöntem şunları yapmaz: yeni basılmış UIWindow
olarak sunulan uyarı görünümü klavyenin altındadır ve kullanıcının düğmelerine dokunmasını engeller. Bunun nedeni, iOS 11'de klavye penceresinden daha yüksek tüm düzeylerin altındaki bir seviyeye düşürülmesidir.
keyWindow
Yine de sunum yapmanın bir özelliği, uyarı sunulduğunda klavyenin aşağı doğru kayması ve uyarı reddedildiğinde tekrar yukarı kaymasıdır. Klavyenin sunum sırasında orada kalmasını istiyorsanız, aşağıdaki kodda gösterildiği gibi üst pencerenin kendisinden sunmayı deneyebilirsiniz:
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
}
}
}
Yukarıdaki kodun o kadar da büyük olmayan kısmı, UIRemoteKeyboardWindow
onu da ekleyebildiğimizden emin olmak için sınıf adını kontrol etmesidir. Bununla birlikte, yukarıdaki kod iOS 9, 10 ve 11 GM tohumunda, doğru renk tonu ile ve klavye kayan eserler olmadan harika çalışıyor.