检查UIAlertController是否已经呈现的最佳方法是什么?

时间:2015-02-02 02:19:51

标签: ios uialertcontroller

我有一个tableview,当加载时,每个单元格都可能返回一个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
}

根据matt的回答,我将扩展名更改为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)
    }
}

14 个答案:

答案 0 :(得分:102)

UIAlertController不是"已经呈现",它是MessagesMasterVC。视图控制器一次只能呈现一个其他视图控制器。因此错误信息。

换句话说,如果您已将视图控制器告知presentViewController:...,则在呈现的视图控制器被解除之前,您无法再次执行此操作。

您可以通过检查其presentedViewController来询问MessagesMasterVC是否已经提供了视图控制器。如果不是nil,请不要告诉presentViewController:... - 它已经提供了一个视图控制器。

答案 1 :(得分:27)

if ([self.navigationController.visibleViewController isKindOfClass:[UIAlertController class]]) {

      // UIAlertController is presenting.Here

}

答案 2 :(得分:8)

嗯,从我的角度来看,上面建议的解决方案存在一个基本问题:

如果你问你的ViewController,是否属性" presentsViewController'是零并且答案是错误的,你不能得出结论,你的UIAlertController已经出现了。它可以是任何呈现的ViewController,例如一个popOver。所以我的建议是肯定检查,警报是否已经在屏幕上是如下(将presentViewController转换为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")
      }
  }

}

答案 3 :(得分:4)

这是我在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)
    }
}

答案 4 :(得分:3)

我们可以简单地检查是否有任何视图控制器。

如果出现,则检查它是否是UIAlertController。

    id alert = self.presentedViewController;

    if (alert && [alert isKindOfClass:[UIAlertController class]]) 
      {
           *// YES UIAlertController is already presented*
      }
    else
       {
        // UIAlertController is not presented OR visible.
       }

答案 5 :(得分:0)

此类别可以自动管理包含UIAlertController的所有模态控制器。

UIViewController+JCPresentQueue.h

答案 6 :(得分:0)

我用它来检测和删除并发出警报。

首先,我们创建具有以下功能的警报。

 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)

    }

答案 7 :(得分:0)

对于最新的Swift语言,您可以使用以下代码:

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;

public class Square
{
    Border borderE = BorderFactory.createEmptyBorder();

    int xPosition;
    int yPosition;

    ImageIcon white = new ImageIcon("empty1.png");
    ImageIcon black = new ImageIcon("empty2.png");
    ImageIcon selectedSquare = new ImageIcon("selected.png");
    ImageIcon redPiece = new ImageIcon("red.png");
    ImageIcon redKing = new ImageIcon("red-king.png");
    ImageIcon whitePiece = new ImageIcon("white.png");
    ImageIcon whiteKing = new ImageIcon("white-king.png");
    JButton btnSquare = new JButton();
    JButton btnPiece = new JButton();
    public boolean isWhite;
    public int pieceHere;

    public Square(int x, int y, boolean isW)
    {
        xPosition = x;
        yPosition = y;
        isWhite = isW;
        int redPieceHere = 1;
        int whitePieceHere = 2;
        int blankSpace = 0;

        btnSquare.setBorder(borderE);
        btnPiece.setBorder(borderE);

        if (isWhite == true)
        {

            btnSquare.setIcon(white);
            //for rows 0,1,2, check black/white, put red if white
            //for rows 5,6,7, check if white, put white piece if white
            for (y = 0; y < 8; y++)
            {

                if (y < 3)
                {
                    pieceHere = redPieceHere;
                    btnPiece.setIcon(redPiece);
                }
                else if(y > 4)
                {
                    pieceHere = whitePieceHere;
                    btnPiece.setIcon(whitePiece);
                }
                else
                {
                    pieceHere = blankSpace;
                }
            }

        }
        else
        {
            btnSquare.setIcon(black);
        }
    }

    public JButton getButton()
    {
        return btnSquare;
    }

    public JButton getPiece()
    {
        return btnPiece;
    }

    public static void main(String[] args)
    {

    }
}

答案 8 :(得分:0)

  

快速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
}}

答案 9 :(得分:0)

关闭当前控制器,并像

一样显示警报控制器
 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)
    }

答案 10 :(得分:0)

您可以-在一行中测试-是否已显示警报:

if self.presentedViewController as? UIAlertController != nil {
    print ("alert already presented")
}

答案 11 :(得分:0)

我发现我需要创建一个队列来堆叠UIAlertController请求。

NSMutableArray *errorMessagesToShow; // in @interface
errorMessagesToShow=[[NSMutableArray alloc] init];  // in init

-(void)showError:(NSString *)theErrorMessage{
    if(theErrorMessage.length>0){
        [errorMessagesToShow addObject:theErrorMessage];
        [self showError1];
    }
}
-(void)showError1{
    NSString *theErrorMessage;
    if([errorMessagesToShow count]==0)return; // queue finished

    UIViewController* parentController =[[UIApplication sharedApplication]keyWindow].rootViewController;
    while( parentController.presentedViewController &&
      parentController != parentController.presentedViewController ){
        parentController = parentController.presentedViewController;
    }
    if([parentController isKindOfClass:[UIAlertController class]])return;  // busy

    // construct the alert using [errorMessagesToShow objectAtIndex:0]
    //  add to each UIAlertAction completionHandler [self showError1];
    //   then

    [errorMessagesToShow removeObjectAtIndex:0];
    [parentController presentViewController:alert animated:YES completion:nil]; 
}

答案 12 :(得分:-1)

当我尝试在UI elements以外的其他帖子中处理Main Thread时,发生了这种情况。当我在过滤器数组块中显示警报时,我遇到了同样的问题。当我将Alert Presenter从过滤器块中取出时,来自控制台的警告消失了。

答案 13 :(得分:-2)

简单地关闭当前控制器并显示您想要的控制器 即。

self.dismiss(animated: false, completion: nil)

self.displayAlertController()