从另一个类调用警报视图,但其中一个不在层次结构中

时间:2015-07-01 09:25:38

标签: ios xcode uialertview hierarchy

我正在尝试从视图控制器中的一个类调用函数:

var rate = RateMyApp.sharedInstance 
rate.showRatingAlert()

并且在RateMyApp类中我调用警报视图:

 var window: AnyObject = UIApplication.sharedApplication().keyWindow!;
        var vc = window.rootViewController;
      vc?!.presentViewController(alert, animated: true, completion: nil)

但是,警报未显示,并且有一种警告:

 Warning: Attempt to present <UIAlertController: 0x15fe3dcf0> on <drawtext.ViewController: 0x16002a800> whose view is not in the window hierarchy!

这种情况经常发生,如果有人隐藏应用程序然后再次打开它,有时会显示警报。

什么会导致这种奇怪的行为?

4 个答案:

答案 0 :(得分:1)

似乎有待解决:

     var window = UIApplication.sharedApplication().keyWindow!
           // var vc = window.rootViewController!!.presentingViewController

        var vc = window.rootViewController;
        while (vc!.presentedViewController != nil)
        {
            vc = vc!.presentedViewController;
        }

      vc?.presentViewController(alert, animated: true, completion: nil)

看起来像Chetan的解决方案

答案 1 :(得分:1)

使用UIAlertController时,应该从视图层次结构中最顶层的ViewController中显示它。

所以我建议:

var rate = RateMyApp.sharedInstance 
rate.showRatingAlert(self)

在RateMyApp类中:

func showRatingAlert(sender:UIViewController){
//..... your UIAlertController here
 sender.presentViewController(alert, animated: true, completion: nil)
}

更一般地说,应该只从最顶层的View Controller调用func presentViewController(:_)

你可以像这样创建一个扩展名:

extension UIViewController {
  @warn_unused_result
  static func topViewController(base: UIViewController? = UIApplication.sharedApplication().windows.first?.rootViewController) -> UIViewController? {

    if let nav = base as? UINavigationController {
        return topViewController(nav.visibleViewController)
    }

    if let tab = base as? UITabBarController {
        let moreNavigationController = tab.moreNavigationController

        if let top = moreNavigationController.topViewController where top.view.window != nil {
            return topViewController(top)
        } else if let selected = tab.selectedViewController {
            return topViewController(selected)
        }
    }

    if let presented = base?.presentedViewController {
        return topViewController(presented)
    }

    if let splitVC = base as? UISplitViewController {
        if let lastVC = splitVC.viewControllers.last {
            return topViewController(lastVC)
        }
        else {
            return splitVC
        }
    }

    if let lastChildVC = base?.childViewControllers.last {
        return topViewController(lastChildVC)
    }

    return base
   }
}

您可以按如下方式拨打电话:

func showRatingAlert() {
   if let vc = UIViewController.topViewController() {
      vc.presentViewController(alert, animated: true, completion: nil)
   }
}

答案 2 :(得分:0)

在窗口启动时执行

dispatch_async(dispatch_get_main_queue(), {
    var window: AnyObject = UIApplication.sharedApplication().keyWindow!;
    var vc = window.rootViewController;
    vc?!.presentViewController(alert, animated: true, completion: nil)
})

答案 3 :(得分:0)

根据我的想法,你只需要

  1. 获取最顶级的viewcontroller [当前呈现]

  2. 提出您的提醒。

  3. 获取最顶层的视图控制器

    [这是obj C代码。请努力转换为swift]

    -(UIViewController*)topViewController {
        return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
    }
    
    -(UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
        if ([rootViewController isKindOfClass:[UITabBarController class]]) {
            UITabBarController* tabBarController = (UITabBarController*)rootViewController;
            return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
        } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
            UINavigationController* navigationController = (UINavigationController*)rootViewController;
            return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
        } else if (rootViewController.presentedViewController) {
            UIViewController* presentedViewController = rootViewController.presentedViewController;
            return [self topViewControllerWithRootViewController:presentedViewController];
        } else {
            return rootViewController;
        }
    }
    

    然后

    UIViewController * topController = [self topViewController];

    现在在topController上显示您的提醒。

    抱歉,我无法为您提供Swift Code。但希望这足以暗示。