I have alertcontroller code like this.
But I try to present alert, the alert don't show to me.
Have any idea to me.
Thanks.
public extension UIAlertController {
func show() {
let win = UIWindow(frame: UIScreen.main.bounds)
let vc = UIViewController()
vc.view.backgroundColor = .clear
win.rootViewController = vc
win.windowLevel = UIWindow.Level.alert + 1
win.makeKeyAndVisible()
vc.present(self, animated: true, completion: nil)
}
}
let alertController = UIAlertController(title: newTitle, message: newMessage, preferredStyle: .alert)
let submit = UIAlertAction(title: submitTitle, style: .default) { (action) in
clickOK()
}
alertController.addAction(submit)
if let cancelTitle = cancelTitle, !cancelTitle.isEmpty {
let cancel = UIAlertAction(title: cancelTitle, style: .cancel) { (action) in
if let clickCancel = clickCancel {
clickCancel()
}
}
alertController.addAction(cancel)
}
alertController.show()
Seems you need to hold UIWindow object until you want to show alert
Here is working code with little changes
private var win: UIWindow!
extension UIAlertController {
func show() {
win = UIWindow(frame: UIScreen.main.bounds)
let vc = UIViewController()
vc.view.backgroundColor = .clear
win.rootViewController = vc
win.windowLevel = .alert + 1
win.makeKeyAndVisible()
win.rootViewController?.present(self, animated: true, completion: nil)
}
open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
win = nil
}
}
usage
Use in same way as you were previously using
let alertController = UIAlertController(title: newTitle, message: newMessage, preferredStyle: .alert)
let submit = UIAlertAction(title: submitTitle, style: .default) { (action) in
clickOK()
}
alertController.addAction(submit)
if let cancelTitle = cancelTitle, !cancelTitle.isEmpty {
let cancel = UIAlertAction(title: cancelTitle, style: .cancel) { (action) in
if let clickCancel = clickCancel {
clickCancel()
}
}
alertController.addAction(cancel)
}
alertController.show()
You can use this swift 5.0 extension also
public extension UIAlertController {
func showAlert() {
let window = UIWindow(frame: UIScreen.main.bounds)
let vc = UIViewController()
vc.view.backgroundColor = .clear
window.rootViewController = vc
window.windowLevel = UIWindow.Level.alert + 1
window.makeKeyAndVisible()
vc.present(self, animated: true, completion: nil)
}
}
Setup your alert controller with title and message and call like this
alertObject.showAlert()
Related
I'm trying to show an alert with a textfield from a modal in swift, but getting an error when I try to show it.
I have to use a UIAlertController because the default alert in Swift doesn't support Textfields currently.
I am calling my modal from my base view with
.sheet(isPresented: $showingLocationSheet) {
LocationSelectionView(selectedLocations: $locations)
}
From my LocationSelectionView, I then call the alert as follows:
let alert = UIAlertController(title: "Add Location", message: "Enter Location Name", preferredStyle: .alert)
alert.addTextField { (name) in
name.placeholder = "Bathroom"
}
let add = UIAlertAction(title: "Add", style: .default) { _ in
print("add Location")
}
let cancel = UIAlertAction(title: "Cancel", style: .destructive)
alert.addAction(add)
alert.addAction(cancel)
DispatchQueue.main.async {
UIApplication.shared.windows.first?.rootViewController?.present(alert, animated: true)
}
but then I receive this error:
Attempt to present <UIAlertController: 0x7fc8a78c7c00> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x7fc8a800b8d0> (from <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x7fc8a800b8d0>) which is already presenting <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x7fc8a6e51980>.
I'm not quite sure how to get it to show here. I've also tried using an extension on the UIAlertController like this:
public extension UIAlertController {
func show() {
let win = UIWindow(frame: UIScreen.main.bounds)
let vc = UIViewController()
vc.view.backgroundColor = .clear
win.rootViewController = vc
win.windowLevel = UIWindow.Level.alert + 1 // Swift 3-4: UIWindowLevelAlert + 1
win.makeKeyAndVisible()
vc.present(self, animated: true, completion: nil)
}
as well as getting the top most controller like so:
func topmostController() -> UIViewController? {
if var topController = UIApplication.shared.keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
return topController
}
return nil
}
but no luck. Any ideas?
protocol AlertDelegate: AnyObject {
func didGetResponse(text: String?)
}
class AlertClass{
weak var delegate: AlertDelegate?
static let sharedInstance = AlertClass()
//Show alert
func alertWindow(title: String, message: String) {
DispatchQueue.main.async(execute: {
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindow.Level.alert + 1
let alert2 = UIAlertController(title: title, message: message, preferredStyle: .alert)
let defaultAction1 = UIAlertAction(title: "Yes", style: .destructive, handler: { action in
print("Yes")
})
let defaultAction2 = UIAlertAction(title: "No", style: .destructive, handler: { action in
print("No")
})
alert2.addAction(defaultAction1)
alert2.addAction(defaultAction2)
alertWindow.makeKeyAndVisible()
alertWindow.rootViewController?.present(alert2, animated: true, completion: nil)
})
}
}
How can I return bool value in this class?
class AlertClass{//This is shared class
weak var delegate: AlertDelegate?
static let sharedInstance = AlertClass()
//Show alert
func alertWindow(title: String, message: String, completion:#escaping (_ result: Bool) -> Void) {
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindow.Level.alert + 1
let alert2 = UIAlertController(title: title, message: message, preferredStyle: .alert)
let defaultAction1 = UIAlertAction(title: "Yes", style: .destructive, handler: { action in
completion(true)
})
let defaultAction2 = UIAlertAction(title: "No", style: .destructive, handler: { action in
print("No")
completion(false)
})
alert2.addAction(defaultAction1)
alert2.addAction(defaultAction2)
alertWindow.makeKeyAndVisible()
alertWindow.rootViewController?.present(alert2, animated: true, completion: nil)
}
}
alert.alertWindow(title: "", message: "Checking Completion") { (result) in
if result{
print("It's yes")
}
else {
print("It's no")
}
}
I'm working with PushNotification on iOS app. I would like to show a UIalertcontroller when the app receive a notification.
I try this code below in the AppDelegate:
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
But the UIAlertcontroller is showing in the root View (First screen) and for other uiviewcontroller i got warning or the app crashes.
try this
Objective-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 and above
var 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: "OK", style: .cancel) { _ 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)
Detail description: http://www.thecave.com/2015/09/28/how-to-present-an-alert-view-using-uialertcontroller-when-you-dont-have-a-view-controller/
Shortest & Simplest :
Create a extension :
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
} }
and then use it anywhere like
UIApplication.topViewController()?.present(UIViewController, animated: true, completion: nil)
With this you can present Alert or anything Anywhere
Example :
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)
ALTERNATE METHOD :
No need to create any Extension or any method or anything simply write the above 3 lines for creating an Alert and for presenting use :
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
That's it.! =)
Anbu.Karthik's answer but in
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)
Thanks for reading this.
Swift 4.1
You can use the following code to present alert from 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)
}
}
For the easiness, I used category
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;
}
Use:
UIAlertController *alertController;
// -- code --
[alertController show];
I have written a static class to make code reusable in swift 4, This class provied different methods for showing alerts.
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)
}
}
I'm working with PushNotification on iOS app. I would like to show a UIalertcontroller when the app receive a notification.
I try this code below in the AppDelegate:
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
But the UIAlertcontroller is showing in the root View (First screen) and for other uiviewcontroller i got warning or the app crashes.
try this
Objective-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 and above
var 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: "OK", style: .cancel) { _ 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)
Detail description: http://www.thecave.com/2015/09/28/how-to-present-an-alert-view-using-uialertcontroller-when-you-dont-have-a-view-controller/
Shortest & Simplest :
Create a extension :
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
} }
and then use it anywhere like
UIApplication.topViewController()?.present(UIViewController, animated: true, completion: nil)
With this you can present Alert or anything Anywhere
Example :
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)
ALTERNATE METHOD :
No need to create any Extension or any method or anything simply write the above 3 lines for creating an Alert and for presenting use :
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
That's it.! =)
Anbu.Karthik's answer but in
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)
Thanks for reading this.
Swift 4.1
You can use the following code to present alert from 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)
}
}
For the easiness, I used category
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;
}
Use:
UIAlertController *alertController;
// -- code --
[alertController show];
I have written a static class to make code reusable in swift 4, This class provied different methods for showing alerts.
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)
}
}
I have a UIWindow that I'm using to display a second UIWindow whose rootViewController is presenting a UIAlertController. When I dismiss the UIAlertController, the main window is nonresponsive, and I'm not sure why. Here's my implementation:
func buttonPressed() {
var window = UIWindow(frame: UIScreen.mainScreen().bounds)
let alert = UIAlertController(title: "Add a comment to your post?", message: "You can also tag your friends.", preferredStyle: UIAlertControllerStyle.Alert)
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: { (action) -> Void in
// this isn't working
window.rootViewController?.dismissViewControllerAnimated(true, completion: nil)
window.removeFromSuperview()
})
let ok = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
// do something
})
alert.addAction(ok)
alert.addAction(cancel)
alert.addTextFieldWithConfigurationHandler({(txtField: UITextField) in
txtField.placeholder = "What's on your mind?"
txtField.keyboardType = UIKeyboardType.Default
txtField.autocapitalizationType = .None
})
window.rootViewController = UIViewController()
window.backgroundColor = UIColor.clearColor()
window.makeKeyAndVisible()
window.rootViewController?.presentViewController(alert, animated: true, completion: nil)
self.addSubview(window)
self.repostButton.setTitle("Pressed!", forState: UIControlState.Normal)
}
Got it. Just called window.hidden = truein the completion handler of cancel. Guess I just overthought it. :)