Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/110.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 只允许从可见视图上的类显示一个UIAlertController视图_Ios_Objective C_Uialertcontroller - Fatal编程技术网

Ios 只允许从可见视图上的类显示一个UIAlertController视图

Ios 只允许从可见视图上的类显示一个UIAlertController视图,ios,objective-c,uialertcontroller,Ios,Objective C,Uialertcontroller,每当我收到来自主题的消息时,我需要显示来自AppDelegate的UIAlertController 我找到了关于如何从AppDelegate显示UIAlertController的代码 UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; topWindow.rootViewController = [UIViewController new]; topWindo

每当我收到来自主题的消息时,我需要显示来自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;
在我的故事板的任何视图上显示警报都没有问题。问题是,每当我收到来自主题的多条消息时,它也会多次显示UIAlertController,从而创建一层UIAlerController,使背景变黑

我尝试了这个代码来解决这个问题,但没有成功

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

如果当前未显示UIAlertController,那么只显示一个UIAlertController的条件应该是什么?

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

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
}
建议的方法 为此,您可以采取两种方法:

  • 创建BaseViewController,在其中添加消息显示方法。从该BaseViewController继承所有ViewController并使用共享方法
  • 创建一个实用程序类,添加一个显示消息的类方法。将该实用程序类添加到,以便可以在任何地方访问它,或者您可以在希望显示消息的任何地方导入它。别忘了添加另一个类方法,它可以获取当前可见的viewcontroller
  • 第一种方法:使用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"];
    
    我个人推荐这种方法。您应该始终显示来自ViewController的消息,而不是某个管理器类。您可以使用块或任何东西将消息返回到ViewController,然后使用此方法显示消息


    第二种方法:使用共享实用程序类。 但是,如果您更喜欢实用程序类方法(例如,如果您坚持直接显示来自manager类的消息,但显然不知道当前哪个ViewController可见),请添加一个实用程序类,让我们假设它称为UIUtilities。现在向其添加两个类方法:

    + (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就会试试这个。我可能会使用第二种方法,因为消息将来自没有视图的类。