我想实现一个单独的ErrorHandler类,它会在某些事件上显示错误消息。应该从不同的其他类调用此类的行为。
发生错误时,它将输出UIAlertView
。
此AlertView的显示应始终位于顶部。因此无论从何处抛出Error,最顶层的viewController都应该显示AlertMessage(例如,当异步后台进程失败时,我想要一条错误消息,无论前景中显示什么视图)。
我找到了几个似乎可以解决我的问题的要点(见下面的代码)。
但是调用UIApplication.sharedApplication().keyWindow?.visibleViewController()
会返回一个零值。
从gist扩展
extension UIWindow {
func visibleViewController() -> UIViewController? {
if let rootViewController: UIViewController = self.rootViewController {
return UIWindow.getVisibleViewControllerFrom(rootViewController)
}
return nil
}
class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
if vc.isKindOfClass(UINavigationController.self) {
let navigationController = vc as! UINavigationController
return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)
} else if vc.isKindOfClass(UITabBarController.self) {
let tabBarController = vc as! UITabBarController
return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)
} else {
if let presentedViewController = vc.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(presentedViewController.presentedViewController!)
} else {
return vc;
}
}
}
}
答案 0 :(得分:23)
Amit89为解决方案带来了一条道路。您必须调用AppDelegate的.window
属性。
所以我从下面的链接更改了Swift代码,以便找到最顶层的ViewController。确保视图已在视图层次结构中。因此,无法从.viewDidLoad
查找最顶层ViewController *
的扩展程序extension UIApplication {
class func topViewController(base: UIViewController? = (UIApplication.sharedApplication().delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
此代码源自Yonat中的GitHub用户comment到ObjectiveC等效项。我只更改了代码位,使其无法使用.keyWindow
属性
答案 1 :(得分:1)
你是否从同一个链接尝试过这个?
let appDelegate = UIApplication.sharedApplication().delegate as! MYAppDelegate//Your app delegate class name.
extension UIApplication {
class func topViewController(base: UIViewController? = appDelegate.window!.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}