我在iOS应用上使用PushNotification。我希望在应用收到通知时显示UIalertcontroller。
我在AppDelegate中尝试以下代码:
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
但是UIAlertcontroller正在根视图(第一个屏幕)中显示,而对于其他uiviewcontroller,我收到警告或应用程序崩溃。
答案 0 :(得分:68)
试试这个
<强>目标C 强>
UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
topWindow.rootViewController = [UIViewController new];
topWindow.windowLevel = UIWindowLevelAlert + 1;
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"APNS" message:@"received Notification" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK",@"confirm") style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
// continue your work
// important to hide the window after work completed.
// this also keeps a reference to the window until the action is invoked.
topWindow.hidden = YES; // if you want to hide the topwindow then use this
topWindow = nil; // if you want to remove the topwindow then use this
}]];
[topWindow makeKeyAndVisible];
[topWindow.rootViewController presentViewController:alert animated:YES completion:nil];
<强> Swift3 强>
let topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
topWindow?.rootViewController = UIViewController()
topWindow?.windowLevel = UIWindow.Level.alert + 1
let alert = UIAlertController(title: "APNS", message: "received Notification", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "confirm"), style: .cancel, handler: {(_ action: UIAlertAction) -> Void in
// continue your work
// important to hide the window after work completed.
// this also keeps a reference to the window until the action is invoked.
topWindow?.isHidden = true // if you want to hide the topwindow then use this
topWindow? = nil // if you want to hide the topwindow then use this
}))
topWindow?.makeKeyAndVisible()
topWindow?.rootViewController?.present(alert, animated: true, completion: nil)
答案 1 :(得分:9)
最短和最短最简单:
创建扩展程序:
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
return controller
} }
然后在任何地方使用它
UIApplication.topViewController()?.present(UIViewController, animated: true, completion: nil)
通过这种方式,您可以显示警报或其他任何地方 示例:
let alert = UIAlertController(title: "Your title", message: "Your message", preferredStyle: .alert)
let cancelButton = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alert.addAction(cancelButton)
UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
替代方法:
无需创建任何扩展或任何方法或任何内容,只需编写以上3行来创建警报并提供使用:
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
那就是它。 =)
答案 2 :(得分:5)
Anbu.Karthik's answer但在 Swift 4.1
var topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
topWindow?.rootViewController = UIViewController()
topWindow?.windowLevel = UIWindowLevelAlert + 1
let alert: UIAlertController = UIAlertController(title: "APNS", message: "received Notification", preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { (alertAction) in
topWindow?.isHidden = true
topWindow = nil
}))
topWindow?.makeKeyAndVisible()
topWindow?.rootViewController?.present(alert, animated: true, completion:nil)
感谢阅读。
答案 3 :(得分:0)
为了方便,我使用了类别
<强> UIAlertController + UIWindow.h 强>
@interface UIAlertController (UIWindow)
- (void)show;
- (void)show:(BOOL)animated;
@end
<强> UIAlertController + UIWindow.m 强>
#import <objc/runtime.h>
@interface UIAlertController (Private)
@property (nonatomic, strong) UIWindow *alertWindow;
@end
@implementation UIAlertController (Private)
@dynamic alertWindow;
- (void)setAlertWindow:(UIWindow *)alertWindow {
objc_setAssociatedObject(self, @selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIWindow *)alertWindow {
return objc_getAssociatedObject(self, @selector(alertWindow));
}
@end
@implementation UIAlertController (UIWindow)
- (void)show {
[self show:YES];
}
- (void)show:(BOOL)animated {
[self setupWindow];
[self.alertWindow.rootViewController presentViewController:self animated:animated completion:nil];
}
- (void)setupWindow {
self.alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.alertWindow.rootViewController = [[UIViewController alloc] init];
id<UIApplicationDelegate> delegate = [UIApplication sharedApplication].delegate;
if ([delegate respondsToSelector:@selector(window)]) {
self.alertWindow.tintColor = delegate.window.tintColor;
}
UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
self.alertWindow.windowLevel = topWindow.windowLevel + 1;
[self.alertWindow makeKeyAndVisible];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
// precaution to insure window gets destroyed
self.alertWindow.hidden = YES;
self.alertWindow = nil;
}
使用强>:
UIAlertController *alertController;
// -- code --
[alertController show];
答案 4 :(得分:0)
我编写了一个静态类,可以在swift 4中重用代码,这个类提供了不同的方法来显示警报。
class AlertUtility: NSObject {
static func showAlert(title: String!, message : String!, viewController: UIViewController) {
let alert = UIAlertController(title: title, message: message ,preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.cancel, handler: nil))
viewController.present(alert, animated: true, completion: nil)
}
static func showAlertAutoDismiss(title: String!, message : String!) -> Void {
//let appDelegate = UIApplication.shared.delegate as! AppDelegate
// the alert view
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let topWindow = UIWindow(frame: UIScreen.main.bounds)
topWindow.rootViewController = UIViewController()
topWindow.windowLevel = UIWindowLevelAlert + 0.8
topWindow.makeKeyAndVisible()
topWindow.rootViewController?.present(alert, animated: true, completion: {})
// change to desired number of seconds (in this case 5 seconds)
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when){
// your code with delay
alert.dismiss(animated: true, completion: nil)
topWindow.isHidden = true
}
}
// Show alert view with call back
static func showAlertWithCB(title: String, message: String, isConditional: Bool, viewController: UIViewController, completionBlock: @escaping (_: Bool) -> Void) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
// Check whether it's conditional or not ('YES' 'NO, or just 'OK')
if isConditional
{
alert.addAction(UIAlertAction(title: NSLocalizedString("yes", comment: ""), style: UIAlertActionStyle.default, handler: { (action: UIAlertAction) in
alert.dismiss(animated: true, completion: nil)
completionBlock(true)
}))
alert.addAction(UIAlertAction(title: NSLocalizedString("no", comment: ""), style: UIAlertActionStyle.default, handler: { (action: UIAlertAction) in
alert.dismiss(animated: true, completion: nil)
completionBlock(false)
}))
}
else
{
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.default, handler: { (action: UIAlertAction) in
alert.dismiss(animated: true, completion: nil)
completionBlock(true)
}))
}
viewController.present(alert, animated: true, completion: nil)
}
static func showAlert(title: String!, message : String!) -> Void {
//let appDelegate = UIApplication.shared.delegate as! AppDelegate
// the alert view
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let topWindow = UIWindow(frame: UIScreen.main.bounds)
topWindow.rootViewController = UIViewController()
topWindow.windowLevel = UIWindowLevelAlert + 1
topWindow.makeKeyAndVisible()
topWindow.rootViewController?.present(alert, animated: true, completion: {})
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.cancel, handler: {(_ action: UIAlertAction) -> Void in
// continue your work
// important to hide the window after work completed.
// this also keeps a reference to the window until the action is invoked.
topWindow.isHidden = true
}))
}
static func showComingSoon(viewController: UIViewController) {
let alert = UIAlertController(title: "", message: "Coming Soon", preferredStyle: .alert)
viewController.present(alert, animated: true, completion: {})
// change to desired number of seconds (in this case 1 seconds)
let when = DispatchTime.now() + 0.6
DispatchQueue.main.asyncAfter(deadline: when){
// your code with delay
alert.dismiss(animated: true, completion: nil)
}
}
static func showGenericErrorMessageAlert(viewController: UIViewController) {
let alert = UIAlertController(title: NSLocalizedString("error", comment: ""), message: NSLocalizedString("generic.error.message", comment: "") ,preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.cancel, handler: nil))
viewController.present(alert, animated: true, completion: nil)
}
static func showAlertWithTextField(viewController : UIViewController,completionBlock: @escaping (_: Bool, String) -> Void) {
//1. Create the alert controller.
let alert = UIAlertController(title: "Report Event?", message: "", preferredStyle: .alert)
alert.view.tintColor = APP_ORANGE_COLOR
//2. Add the text field. You can configure it however you need.
//AlertUtility.addte
alert.addTextField { (textField) in
let heightConstraint = NSLayoutConstraint(item: textField, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 50)
textField.addConstraint(heightConstraint)
textField.placeholder = "Enter report reason here"
textField.tintColor = APP_ORANGE_COLOR
textField.autocapitalizationType = .sentences
}
// 3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
// Force unwrapping because we know it exists.
completionBlock(true,"")
//print("Text field: \(textField.text)")
}))
// 3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "Submit", style: .default, handler: { [weak alert] (_) in
let textField = alert?.textFields![0] // Force unwrapping because we know it exists.
completionBlock(true,(textField?.text)!)
//print("Text field: \(textField.text)")
}))
// 4. Present the alert.
viewController.present(alert, animated: true, completion: nil)
let textField = alert.textFields![0]
let v = UIView.init(frame: textField.frame)
textField.addSubview(v)
v.frame = textField.frame
v.bounds = textField.bounds
v.backgroundColor = APP_ORANGE_COLOR
v.superview?.bringSubview(toFront: v)
}
}
答案 5 :(得分:0)
Swift 4.1 您可以使用以下代码从AppDelegate发出警报
func showAlertFromAppDelegates(){
let alertVC = UIAlertController(title: "Oops" , message: "Presented Alert from AppDelegates", preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Okay", style: UIAlertActionStyle.cancel) { (alert) in
exit(0) // Your code here
}
alertVC.addAction(okAction)
DispatchQueue.main.async {
var presentVC = self.window?.rootViewController
while let next = presentVC?.presentedViewController {
presentVC = next
}
presentVC?.present(alertVC, animated: true, completion: nil)
}
}