在视图控制器之外显示UIAlertController

16

我有困难显示我的UIAlertController,因为我正在试图在一个不是ViewController的类中显示它。

我已经尝试添加它:

 var alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert)

UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

哪一种方法没有起作用......我还没有找到适合我的解决方法。


你的类不是一个UIViewController,这部分是无法测试的。考虑添加委托或基于块的回调,在使用此类的视图控制器上显示警报。 - 3lvis
4个回答

38

我编写了这个扩展程序,为了恢复show()方法而对UIAlertController进行了修改。
它使用递归来查找当前顶部视图控制器:

extension UIAlertController {
    
    func show() {
        present(animated: true, completion: nil)
    }
    
    func present(animated: Bool, completion: (() -> Void)?) {
        if let rootVC = UIApplication.shared.keyWindow?.rootViewController {
            presentFromController(controller: rootVC, animated: animated, completion: completion)
        }
    }
    
    private func presentFromController(controller: UIViewController, animated: Bool, completion: (() -> Void)?) {
        if 
            let navVC = controller as? UINavigationController,
            let visibleVC = navVC.visibleViewController
        {
            presentFromController(controller: visibleVC, animated: animated, completion: completion)
        } else if
            let tabVC = controller as? UITabBarController,
            let selectedVC = tabVC.selectedViewController
        {
            presentFromController(controller: selectedVC, animated: animated, completion: completion)
        } else if let presented = controller.presentedViewController {
            presentFromController(controller: presented, animated: animated, completion: completion)
        } else {
            controller.present(self, animated: animated, completion: completion);    
        }
    }
}
现在只需要这样简单的步骤:
var alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert)
alertController.show()

太好了!非常感谢。 - Michael
1
很高兴它对你有用,我已经在许多VC场景中使用它(模态vc在选项卡栏控制器内的导航堆栈等),如果有情况无法正常工作,请告诉我... - Aviel Gross
SharedApplication不能在应用程序扩展中使用。 - SAHM
2
在键视图控制器已经以模态方式呈现某些内容的情况下,这种方法不起作用。我不得不添加另一个检查 if let presented = controller.presentedViewController { presentFromController(controller: presented, animated: animated, completion: completion) } else { controller.present(self, animated: animated, completion: completion) } - Tim

3

这应该可以工作。

 UIApplication.sharedApplication().windows[0].rootViewController?.presentViewController(...)

1
创建一个辅助函数,在当前视图控制器中调用并将当前视图控制器作为参数传递:
func showAlertInVC(
  viewController: UIViewController, 
  title: String, 
message: String)
{
  //Code to create an alert controller and display it in viewController
}

0
如果你的解决方案不起作用,可能是因为那个时候没有窗口。 我曾经在尝试在“application:DidFinishLoadingWithOptions”方法中显示警示视图时遇到相同的问题。 在这种情况下,我的解决方案是检查根视图控制器是否可用,如果不可用,则添加“UIApplicationDidBecomeActiveNotification”的通知。
NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationDidBecomeActiveNotification,
                object: nil,
                queue: NSOperationQueue.mainQueue()) {
                    (_) in
                        //show your alert by using root view controller
                        //remove self from observing
                    }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接