仅允许从Visible视图上的Class显示一个UIAlertController视图

时间:2017-05-25 06:30:30

标签: ios objective-c uialertcontroller

每当我收到来自主题的消息时,我都需要显示来自AppDelegate的UIAlertController。

我找到了关于如何从AppDelegate显示UIAlertController的代码。

UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    topWindow.rootViewController = [UIViewController new];
    topWindow.windowLevel = UIWindowLevelAlert + 1;

UIAlertController *uiAlert= ...

topWindow.hidden = YES;

在我的故事板中的任何视图上显示警报都没有问题。问题是每当我收到Topic的多条消息时,它也会多次显示UIAlertController,创建一层UIAlerController,使背景变黑。

我尝试使用此代码来解决问题,但它没有

if (![topWindow.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
            [topWindow makeKeyAndVisible];
            [topWindow.rootViewController presentViewController:uiAlert animated:YES completion:nil];
        }

如果没有呈现当前的UIAlertController,那么只提供一个UIAlertController应该是什么条件?

2 个答案:

答案 0 :(得分:1)

func checkIfAlertHasPresented() -> UIAlertController?
{
    if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController
    {
        while let presentedVC = topController.presentedViewController
        {
            topController = presentedVC
        }
        if topController is UIAlertController
        {
            return (topController as! UIAlertController)
        }
        else
        {
            return nil
        }
    }
    return nil
}

答案 1 :(得分:1)

我建议不要这样做,从AppDelegate。绝对没有必要搞乱rootViewController。

建议的方法

您可以采取两种方法:

  1. 创建一个BaseViewController,在其中添加显示方法的消息。从该BaseViewController继承所有ViewControllers并使用共享方法。
  2. 创建一个实用程序类,添加一个显示消息的类方法。将该实用程序类添加到your pch file,以便可以在任何地方访问它,或者只需将其导入到要显示消息的位置即可。别忘了添加另一个获取当前可见viewcontrller的Class方法。
  3. 第一种方法:使用BaseViewController(推荐)

    如果您使用的是BaseViewController方法,您的方法将如下所示:

    -(void) showMessageWithHeader:(NSString *)header
                          andBody:(NSString *)bodyMessage{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:header message:bodyMessage preferredStyle:UIAlertControllerStyleActionSheet];
        UIAlertAction * okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
    
        }];
        [alertController addAction:okAction];
        [self presentViewController:alertController animated: YES completion: nil];
    }
    

    您可以在从您的基础继承的任何ViewController中使用它,如下所示:

    [self showMessageWithHeader:@"Alert"
                        andBody:@"This message was generated from base class"];
    

    我个人推荐这种方法。你应该总是从ViewControllers中显示你的消息,而不是让我们说一些经理类。您可以使用块或其他任何方法将消息返回到ViewController,然后使用此方法显示它。

    第二种方法:使用共享实用程序类。

    但是,如果您更喜欢实用程序类方法(例如,如果您坚持直接从您的经理类中显示消息,而这显然不知道哪个ViewController当前可见),请添加一个utilityClass,让'假设它被称为UIUtilities。现在添加两个Class方法:

    + (UIViewController *) getVisibleViewController{
        UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
        topController = [UIUtilities getVisibleViewControllerFrom:topController];
    
        return topController;
    }
    
    + (UIViewController *) getVisibleViewControllerFrom:(UIViewController *) vc {
        if ([vc isKindOfClass:[UINavigationController class]]) {
            return [UIUtilities getVisibleViewControllerFrom:[((UINavigationController *) vc) visibleViewController]];
        } else if ([vc isKindOfClass:[UITabBarController class]]) {
            return [UIUtilities getVisibleViewControllerFrom:[((UITabBarController *) vc) selectedViewController]];
        } else {
            if (vc.presentedViewController) {
                return [UIUtilities getVisibleViewControllerFrom:vc.presentedViewController];
            } else {
                return vc;
            }
        }
    }
    

    使用+ (UIViewController *) getVisibleViewController将返回当前可见的ViewController。完成该部分后,您现在可以添加类方法以在VisibleViewController上显示消息:

    +(void) showMessageWithHeader:(NSString *)header
                          andBody:(NSString *)bodyMessage{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:header message:bodyMessage preferredStyle:UIAlertControllerStyleActionSheet];
        UIAlertAction * okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
    
        }];
        [alertController addAction:okAction];
        if(![[UIUtilities getVisibleViewController] isKindOfClass:[UIAlertController class]]){
                 [[UIUtilities getVisibleViewController] presentViewController:alertController animated: YES completion: nil];
        }
    
    }
    

    现在,您可以在任何想要显示消息的地方调用此方法:

    [UIUtilities showMessageWithHeader:@"Alert"
                               andBody:@"This message came from Utility class"];
    

    这将一次只显示一个警报。如果一个警报已经可见,则其他警报将无法显示。我不会这样做,但既然这就是你想要的,哦,好吧。

    现在无论收到多少消息,它们都将叠加在当前可见的ViewController上,您可以逐个解除它们(或者根据您的需要,一次只能看到一个警报,具体取决于您的方法没有任何额外的麻烦。