【问题标题】:Allow only one UIAlertController View to be presented from a Class on the Visible view只允许一个 UIAlertController 视图从可见视图上的类中呈现
【发布时间】:2017-05-25 06:30:29
【问题描述】:

每当我收到来自主题的消息时,我都需要显示来自 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 的条件应该是什么?

【问题讨论】:

标签: ios objective-c uialertcontroller


【解决方案1】:

我建议不要从 AppDelegate 这样做。完全没有必要去搞乱rootViewController。

建议的方法

您可以采取两种方法:

  1. 创建一个BaseViewController,在其中添加消息显示方法。从该 BaseViewController 继承所有 ViewController 并使用共享方法。
  2. 创建一个实用程序类,添加一个显示消息的类方法。将该实用程序类添加到 your pch file 以便可以在任何地方访问它,或者您可以将它导入到您想要显示消息的任何位置。不要忘记添加另一个获取当前 Visible viewcontrller 的 Class 方法。

第一种方法:使用 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 当前可见),添加一个实用程序类,假设它称为 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 上,您可以简单地一一关闭它们(或者根据您的需要,一次只显示一个警报,具体取决于您的方法采取),没有任何额外的麻烦。

【讨论】:

  • 哇,这看起来很有希望。我已经下班了,但我一到 tmrw 就会试试这个。我可能会采用第二种方法,因为消息将来自没有视图的类。
【解决方案2】:
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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多