I am new to swift, i want to dismiss the alert which is present on
screen when the new alert comes.
I tried:
func showDefaultAlert(controller: UIViewController, title: String, message: String) {
// create the alert
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
// add an action (button)
alert.addAction(UIAlertAction(title: defaultTextForNormalAlertButton, style: UIAlertActionStyle.Default, handler: nil))
// show the alert
//controller.presentViewController(alert, animated: true, completion: nil)
self.showAlert(controller, alert: alert)
}
func showAlert(controller: UIViewController, alert: UIAlertController) {
if let currentPresentedViewController = UIApplication.sharedApplication().keyWindow?.rootViewController?.presentedViewController {
if currentPresentedViewController.isKindOfClass(UIAlertController) {
currentPresentedViewController.dismissViewControllerAnimated(false, completion: {
controller.presentViewController(alert, animated: true, completion: nil)
})
}else {
controller.presentViewController(alert, animated: true, completion: nil)
}
}
}
}
// Call to above method in view controller class:
SPSwiftAlert.sharedObject.showDefaultAlert(self, title:"Title1", message1: "Message")
SPSwiftAlert.sharedObject.showDefaultAlert(self, title:"Title2", message: "Message2")
-
but the above code giving the run time error as :
Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UIAlertController: 0x7fceb95dcfb0>)
After presenting the UIAlertController you can check its visibility as below:
Presented UIAlertController:
let alerts=UIAlertController(title: "Test", message: "Test", preferredStyle: .Alert)
presentViewController(alerts, animated: true, completion: nil)
Check if the UIAlertController is visible:
if (alerts.isViewLoaded())
{
print("Visible")
//Here you can dismiss the controller
//dismissViewControllerAnimated(true, completion: nil)
}
Check out this demo: Source code
Related
I'm trying to dismiss the current view controller in the completion handler of a UIAlertAction, but it is not dismissing. I have written the following code (The loading indicator is simply a loading alert controller that I dismiss when the data was successfully uploaded):
loadingIndicator.dismiss(animated: true) {
let success = UIAlertController(title: "Successfully Uploaded", message: "", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { _ in
print("Ok selected") //this is working correctly
self.dismiss(animated: true, completion: nil) //this is not
})
success.addAction(ok)
self.present(success, animated: true, completion: nil)
}
However, after clicking on "Ok" in the alert, "Ok selected" is printed but the view controller is not dismissed. Nothing else shows up in the debugger.
Try dismissing it on Main thread and also check if ViewController is presented or pushed in navigation hierarchy.
loadingIndicator.dismiss(animated: true) {
let success = UIAlertController(title: "Successfully Uploaded", message: "", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { _ in
DispatchQueue.main.async {
self.dismiss(animated: true, completion: nil)
// If pushed use PopViewController on navigation
// self.navigationController?.popViewController(animated: true)
}
})
success.addAction(ok)
self.present(success, animated: true, completion: nil)
}
To check if ViewController is being presented or not use self.isBeingPresented property.
I have a UIViewController which is embedeed in UINavigationController which is being presented modally over my application's keyWindow.rootViewController. When I present UIAlertController in any screen of the presented navigation controller, the alert controller is correctly displayed but the closures for any of the UIAlertAction are not being called after being pressed.
I am displaying the same alert controller with the same code in view controllers belonging to the main navigation controller of my app and the closures are called properly.
The code for presenting the alert is very simple, here's the snippet:
// Creating Alert
func createAlert() -> UIAlertController {
let actions: [UIAlertAction] = [
UIAlertAction(title: "Something", style: .default, handler: { _ in
self.setOriginalQueue(with: items, description: description, identifier: identifier)
self.setQueue()
}),
UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
normal()
})
]
let alert = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet, actions: actions)
return alert
}
// In ViewController
DispatchQueue.main.async {
self.present(alert, animated: true, completion: nil)
}
So the question is, why are the closures not being called?
UIAlertController does not contain four types argument. See the document.
Once you fixed that, the rest will be automatically fixed like below.
For everyone's convenience I'll put the whole Modal view controller class source here.
class ModalViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.present(createAlert(), animated: true, completion: nil)
}
func createAlert() -> UIAlertController {
let actions: [UIAlertAction] = [
UIAlertAction(title: "Something", style: .default, handler: { _ in
print("Something")
}),
UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
print("Cancel")
})
]
let alert = UIAlertController(title: "Title", message: "Message", preferredStyle: .actionSheet)
for action in actions {
alert.addAction(action)
}
return alert
}
}
The line is wrong.
let alert = UIAlertController(title: nil, message: "message" , preferredStyle: .actionSheet, actions: actions)
You must be get error like that
Type of expression is ambiguous without more context
Change it like that:
return UIAlertController(title: YourTitle, message: YourMessage, preferredStyle: UIAlertController.Style.actionSheet)
So it can work.
Need to pass name of the method when you are presenting alert
self.present(createAlert(), animated: true, completion: nil)
func displayalert(title:String, message:String, vc:UIViewController)
{
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction((UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
self.dismiss(animated: true, completion: nil)
})))
vc.present(alert, animated: true, completion: nil)
}
this is the function i have used.i tried to call it like this,
displayalert1(title:"dsfvasdcs", message:"easfSDXCSDZX", vc:validateOTPViewController())
it is returning error "BAD ACCESS". the vc.present is running like a loop. I cant understand what the problem is.
I run your code and it working fine. I thing you would pass self in vc.
self.displayalert(title: "Title", message: "Some Message", vc: self)
You can also make an extension of UIViewController-
extension UIViewController {
// Your Function...
}
Now You can globally access this function from any view controller, Just by typing-
self.displayalert(title: "Title", message: "Some Message", vc: self)
You're passing a new instance of the validateOTPViewController to the displayalert function.
Change it to:
displayalert1(title:"dsfvasdcs", message:"easfSDXCSDZX", vc:self)
This will pass the current view controller to the function instead of a new one that hasn't been presented.
Swift 4
Create an extension of UIViewController with your function to display alert with required parameter arguments
extension UIViewController {
func displayalert(title:String, message:String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction((UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
alert.dismiss(animated: true, completion: nil)
})))
self.present(alert, animated: true, completion: nil)
}
}
Now call this function from your view controller:
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.displayalert(title: <String>, message: <String>)
}
}
I have this function and I use it on almost all viewController´s that I have, for some reason went I push "ok" to dismiss the pop up, it switches to another viewController.
this is my function...
extension UIViewController
{
func displayAlert(title: String, message: String)
{
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction((UIAlertAction(title: "Ok", style: .Default, handler:
{ (action) -> Void in
self .dismissViewControllerAnimated(true, completion: nil)
})))
self.presentViewController(alert, animated: true, completion: nil)
}
}
any help? I'm using Xcode 7.0 beta 6 with swift 2
You don't need to dismiss the alert controller yourself. That happens automatically with your alert action. You're simply providing a closure that gets called when that "OK" action gets triggered. Just remove this line:
self.dismissViewControllerAnimated(true, completion: nil)
I have a view controller which is modally presented and when i run UIAlertController, keep getting a error message . how can i work around this.
the alert is trigged from a button which checks a text field is empty or not.
#IBAction func registerAction(sender: AnyObject) {
if(userEmail.isEmpty){
alertMessage("Fields Are Empty")
}
}
func alertMessage(userMessage:String){
var myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
}
Error when i run the alert
Warning: Attempt to present <UIAlertController: 0x7f9bbb9060d0> on <AlertApp.CustomSignupVC: 0x7f9bb94accb0> which is already presenting <UIAlertController: 0x7f9bbb926660>
Try to add it in main operation queue.
dispatch_async(dispatch_get_main_queue()) {
self.presentViewController(myAlert, animated: true, completion: nil)
}
Check this relative question : Presenting a view controller modally from an action sheet's delegate in iOS8 - iOS10