ロードされたときに各セルがNSErrorを返す可能性のあるテーブルビューがあり、これをUIAlertControllerに表示することを選択しました。問題は、複数のエラーが返された場合、コンソールでこのエラーが発生することです。
警告:MessagesMasterVCでUIAlertController:0x14e64cb00を表示しようとしています:0x14e53d800は既に表示されています(null)
理想的には、UIAlertController拡張メソッドでこれを処理するのが理想的です。
class func simpleAlertWithMessage(message: String!) -> UIAlertController {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
alertController.addAction(cancel)
return alertController
}
マットの答えに基づいて、拡張機能をUIViewController拡張機能に変更しました。これは、はるかにクリーンで、多くのpresentViewControllerコードを保存します。
func showSimpleAlertWithMessage(message: String!) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
alertController.addAction(cancel)
if self.presentedViewController == nil {
self.presentViewController(alertController, animated: true, completion: nil)
}
}
「既に表示」されているのはUIAlertControllerではなく、MessagesMasterVCです。 View Controllerは、一度に他のView Controllerを1つしか表示できません。したがって、エラーメッセージ。
つまり、View ControllerにpresentViewController:...
を指示した場合、表示されたView Controllerが破棄されるまで、それを再度行うことはできません。
presentedViewController
を調べることにより、Views ControllerがすでにView Controllerを提供しているかどうかをMessagesMasterVCに問い合わせることができます。 nil
でない場合は、presentViewController:...
に伝えないでください-すでにView Controllerを提供しています。
if ([self.navigationController.visibleViewController isKindOfClass:[UIAlertController class]]) {
// UIAlertController is presenting.Here
}
まあ、上記の提案された解決策は私の観点から本質的な問題を抱えています:
ViewControllerに尋ねると、属性 'presentedViewController'がnilであり、答えがfalseであるかどうかにかかわらず、UIAlertControllerが既に表示されているという結論に達することはできません。提示されたViewController、たとえばpopOver。したがって、アラートが既に画面に表示されているかどうかを確認するための私の提案は次のとおりです(presentedViewControllerをUIAlertControllerとしてキャストします)。
if self.presentedViewController == nil {
// do your presentation of the UIAlertController
// ...
} else {
// either the Alert is already presented, or any other view controller
// is active (e.g. a PopOver)
// ...
let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController?
if thePresentedVC != nil {
if let thePresentedVCAsAlertController : UIAlertController = thePresentedVC as? UIAlertController {
// nothing to do , AlertController already active
// ...
print("Alert not necessary, already on the screen !")
} else {
// there is another ViewController presented
// but it is not an UIAlertController, so do
// your UIAlertController-Presentation with
// this (presented) ViewController
// ...
thePresentedVC!.presentViewController(...)
print("Alert comes up via another presented VC, e.g. a PopOver")
}
}
}
Swift 3で使用するソリューションを次に示します。ユーザーにアラートを表示する機能です。ユーザーがアラートを閉じる前に何度も呼び出すと、新しいアラートテキストが追加されます。既に表示されているアラート。他のビューが表示されている場合、アラートは表示されません。すべてがその動作に同意するわけではありませんが、単純な状況ではうまく機能します。
extension UIViewController {
func showAlert(_ msg: String, title: String = "") {
if let currentAlert = self.presentedViewController as? UIAlertController {
currentAlert.message = (currentAlert.message ?? "") + "\n\nUpdate:\(title): \(msg)"
return
}
// create the alert
let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
// show the alert
self.present(alert, animated: true, completion: nil)
}
}
View Controllerが表示されているかどうかを確認するだけです。
提示された場合、それがUIAlertControllerの種類であるかどうかを確認します。
id alert = self.presentedViewController;
if (alert && [alert isKindOfClass:[UIAlertController class]])
{
*// YES UIAlertController is already presented*
}
else
{
// UIAlertController is not presented OR visible.
}
Swift 4.2+回答
if UIApplication.topViewController()!.isKind(of: UIAlertController.self) {
print("UIAlertController is presented")}
ViewControllerの最上位を取得する方法がわからない場合
extension UIApplication {
public class func topViewController(_ base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(presented)
}
return base
}}
現在のコントローラーを閉じて、アラートコントローラーを次のように表示します
func alert(_ message:String) {
let alert = UIAlertController(title: "Error!", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
self.dismiss(animated: false, completion: nil)
self.present(alert, animated: true,completion: nil)
}
私はそれを使用して、検出と削除と警告を行いました。
まず、次の機能を使用してアラートを作成します。
var yourAlert :UIAlertController!
func useYouAlert (header: String, info:String){
yourAlert = UIAlertController(title:header as String, message: info as String, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: self.langText[62]as String, style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
print("OK")
}
yourAlert.addAction(okAction)
self.present(yourAlert.addAction, animated: true, completion: nil)
}
そして、コードの他の部分で
if yourAlert != nil {
yourAlert.dismiss(animated: true, completion: nil)
}
アラートが既に表示されている場合、1行でテストできます。
if self.presentedViewController as? UIAlertController != nil {
print ("alert already presented")
}
最新のSwift言語については、次を使用できます。
var alert = presentedViewController
if alert != nil && (alert is UIAlertController) {
// YES UIAlertController is already presented*
} else {
// UIAlertController is not presented OR visible.
}
このカテゴリは、UIAlertControllerのすべてのモーダルコントローラーを自動管理できます。