ios - 从另一个类调用警报 View ,但不在层次结构中

标签 ios xcode uialertview hierarchy

我正在尝试从 View Controller 中的一个类调用函数:

var rate = RateMyApp.sharedInstance 
rate.showRatingAlert()

在 RateMyApp 类中,我调用警报 View :

 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!

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

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

最佳答案

在使用 UIAlertController 时,它应该从 View 层次结构中最顶层的 ViewController 呈现。

所以我建议:

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

在 RateMyApp 类中:

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

一般来说,函数 presentViewController(:_) 应该只从最顶层的 View Controller 调用。

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

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)
   }
}

关于ios - 从另一个类调用警报 View ,但不在层次结构中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31157448/

相关文章:

设备上的 iOS 测试应用程序,两个不同的区域

ios - 在 UIAlertView 中更改按钮标题颜色

ios - UIAlertView 中的动画图像

ios - 如何为以下场景安排本地通知?

ios - 从父项中删除 mapView,然后再添加回去

ios - 如何快速切换到最后一页上的不同 View Controller ?

ios - 为 ImageView 设置渐变背景,旋转

ios - Xcode 10 beta 6 Whole Module 设置导致 "cannot have input files with file list"错误

iphone - 如何用多个其他字符串 [NSString] 替换多个字符串的出现

ios - 在 Swift 3 中使用 Firebase 对 OneSignal 进行身份验证以将自动通知发送到分段