我正在尝试从视图控制器中的一个类调用函数:
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!
这种情况经常发生,如果有人隐藏应用程序然后再次打开它,有时会显示警报。
什么会导致这种奇怪的行为?
答案 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)
根据我的想法,你只需要
获取最顶级的viewcontroller [当前呈现]
提出您的提醒。
获取最顶层的视图控制器
[这是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。但希望这足以暗示。