objective example custom ios objective-c iphone swift3 uialertcontroller

ios - example - Cómo mostrar UIAlertController desde Appdelegate



uialertcontroller swift 4 (5)

Estoy trabajando con PushNotification en la aplicación iOS. Me gustaría mostrar un controlador de UIalert cuando la aplicación reciba una notificación.

Intento este código a continuación en el AppDelegate:

[self.window.rootViewController presentViewController:alert animated:YES completion:nil];

Pero el UIAlertcontroller se muestra en la vista raíz (Primera pantalla) y para otro uiviewcontroller recibí una advertencia o la aplicación se bloquea.


Más corto y más simple:

Crear una extensión:

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

y luego usarlo en cualquier lugar como

UIApplication.topViewController()?.present(UIViewController, animated: true, completion: nil)

Con esto puedes presentar Alert o cualquier ejemplo en cualquier lugar :

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)

METODO ALTERNATIVO :

No es necesario crear ninguna Extensión ni ningún método ni nada, simplemente escriba las 3 líneas anteriores para crear una Alerta y para presentar su uso:

self.window?.rootViewController?.present(alert, animated: true, completion: nil)

Eso es.! =)


He escrito una clase estática para hacer que el código sea reutilizable en swift 4, esta clase probó diferentes métodos para mostrar alertas.

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


Para la facilidad, utilicé categoría.

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

Uso :

UIAlertController *alertController; // -- code -- [alertController show];


Por encima de la respuesta, pero en 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)

Gracias por leer esto.


prueba esto

C objetivo

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

var topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds) topWindow.rootViewController = UIViewController() topWindow.windowLevel = UIWindowLevelAlert + 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: { _ in })

Rápido

var topWindow: UIWindow? = UIWindow(frame: UIScreen.mainScreen().bounds) topWindow.rootViewController = UIViewController() topWindow.windowLevel = UIWindowLevelAlert + 1 var alert: UIAlertController = UIAlertController.alertControllerWithTitle("APNS", message: "received Notification", preferredStyle: .Alert) alert.addAction(UIAlertAction.actionWithTitle(NSLocalizedString("OK", "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.hidden = true // 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: true, completion: { _ in })

Descripción detallada: http://www.thecave.com/2015/09/28/how-to-present-an-alert-view-using-uialertcontroller-when-you-dont-have-a-view-controller/