场景:用户点击视图控制器上的按钮。视图控制器是导航堆栈中最顶层的(很明显)。tap调用在另一个类上调用的实用程序类方法。这里发生了不好的事情我想在控件返回到视图控制器之前在那里显示一个警告。
+ (void)myUtilityMethod {
// do stuff
// something bad happened, display an alert.
}
这是可能的UIAlertView(但可能不太合适)。
在这种情况下,你如何在myUtilityMethod中呈现UIAlertController ?
斯威夫特5
我刚刚创建了一个新窗口,并在其中添加了警报视图控制器。
查看类TopViewController:
https://gist.github.com/odnaks/3f3fd0d20f318c6276e76d0f9d7de5a7
我使用它很简单,像UIAlertController:
let alert = TopAlertController()
alert.title = "title"
alert.message = "message"
alert.addAction(UIAlertAction(title: "Ок", style: .default, handler: { _ in }))
alert.show()
@agilityvision的答案翻译为Swift4/iOS11。我没有使用本地化字符串,但你可以很容易地改变:
import UIKit
/** An alert controller that can be called without a view controller.
Creates a blank view controller and presents itself over that
**/
class AlertPlusViewController: UIAlertController {
private var alertWindow: UIWindow?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.alertWindow?.isHidden = true
alertWindow = nil
}
func show() {
self.showAnimated(animated: true)
}
func showAnimated(animated _: Bool) {
let blankViewController = UIViewController()
blankViewController.view.backgroundColor = UIColor.clear
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = blankViewController
window.backgroundColor = UIColor.clear
window.windowLevel = UIWindowLevelAlert + 1
window.makeKeyAndVisible()
self.alertWindow = window
blankViewController.present(self, animated: true, completion: nil)
}
func presentOkayAlertWithTitle(title: String?, message: String?) {
let alertController = AlertPlusViewController(title: title, message: message, preferredStyle: .alert)
let okayAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
alertController.addAction(okayAction)
alertController.show()
}
func presentOkayAlertWithError(error: NSError?) {
let title = "Error"
let message = error?.localizedDescription
presentOkayAlertWithTitle(title: title, message: message)
}
}
几个月前我发过一个类似的问题,我想我终于解决了这个问题。如果你只是想看代码,请点击我文章底部的链接。
解决方案是使用一个额外的UIWindow。
当你想要显示你的UIAlertController:
使你的窗口成为键和可见窗口(window. makekeyandvisible ())
只需使用一个普通的UIViewController实例作为新窗口的rootViewController。(窗口。rootViewController = UIViewController())
在你窗口的rootViewController上显示你的UIAlertController
有几点需要注意:
你的UIWindow必须是强引用的。如果它没有被强引用,它将永远不会出现(因为它已经被释放了)。我建议使用属性,但我也成功地使用了关联对象。
为了确保窗口显示在其他所有内容之上(包括系统UIAlertControllers),我设置了windowLevel。(窗口。windowLevel = UIWindowLevelAlert + 1)
最后,我有一个完整的实现,如果你只是想看看。
https://github.com/dbettermann/DBAlertController
Kevin Sliech提供了一个很好的解决方案。
我现在在我的主UIViewController子类中使用下面的代码。
我做的一个小改动是检查最好的表示控制器是不是一个普通的UIViewController。如果不是,那就一定是某个VC表示一个普通VC。因此,我们返回正在呈现的VC。
- (UIViewController *)bestPresentationController
{
UIViewController *bestPresentationController = [UIApplication sharedApplication].keyWindow.rootViewController;
if (![bestPresentationController isMemberOfClass:[UIViewController class]])
{
bestPresentationController = bestPresentationController.presentedViewController;
}
return bestPresentationController;
}
在我的测试中似乎一切正常。
谢谢你,凯文!
你可以用Swift 2.2做以下事情:
let alertController: UIAlertController = ...
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
Swift 3.0:
let alertController: UIAlertController = ...
UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)