UIAlertController Will Not Display - In Swift

I created ContactUsViewController .

In this controller, the user will select an option from pickerView , and then enter the message into textView and click the "Send Email" button.

When they click the button, it creates an MFMailComposeViewController to send the email. Now that the email has been sent, saved, canceled, or has worked, the MFMailComposeViewController closes as it returns to my application. I want a warning to appear next to give them an update on what ever happened. I initially set this using UIAlertView and put this code in the fun mailComposeController function, see below:

 func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) { switch result.rawValue { case MFMailComposeResultCancelled.rawValue: NSLog("Email cancelled") case MFMailComposeResultSaved.rawValue: NSLog("Email saved") let sendMailErrorAlert = UIAlertView(title: "Email saved", message: "Your email has been saved in Mail.", delegate: self, cancelButtonTitle: "OK") sendMailErrorAlert.show() case MFMailComposeResultSent.rawValue: NSLog("Email sent") let alertController = UIAlertController(title: "test", message: "test", preferredStyle: .Alert) let okButton = UIAlertAction(title: "Okay", style: .Default, handler: nil) alertController.addAction(okButton) presentViewController(alertController, animated: true, completion: nil) case MFMailComposeResultFailed.rawValue: NSLog("Email failed: %@", [error!.localizedDescription]) let sendMailErrorAlert = UIAlertView(title: "Oops!", message: "Looks like something went wrong, and the email couldn't send. Please try again later.", delegate: self, cancelButtonTitle: "OK") sendMailErrorAlert.show() default: break } 

As you can see, I used UIAlertView for email with saved and email. This works absolutely fine and shows my warning as expected.

I recently read that UIAlertView depreciating with iOS 8, and now we have to use UIAlertController . So I tried to create the same using the UIAlertController , which you can see in the "Sent emails" section. However, this does not seem to work, it just does not show any warnings. He prints this error in the logs:

 Warning: Attempt to present <UIAlertController: 0x126c50d30> on <XXXX.ContactUsViewController: 0x1269cda70> whose view is not in the window hierarchy! 

But I'm not quite sure what that says, or, more importantly, how to fix it.

My questions:

  • Am I saying correctly that I cannot use UIAlertView ?
  • How can I fix this and make the UIAlerController appear after I return from the Mail application?

Thanks in advance.

+5
source share
3 answers

The problem is that by the time this function is called:

 present(alertController, animated: true, completion: nil) 

your mail view controller is still displayed. You must make sure that alertController displayed at the top of the window hierarchy. In your example, you have the following window hierarchy:

 +---------------------------+ | MailComposeViewController | +---------------------------+ || +---------------------------+ | ContactUsViewController | +---------------------------+ 

Instead, you must first close the email view manager. When this is done, show you the warning controller.

 let alertController = UIAlertController(title: "test", message: "test", preferredStyle: .Alert) let okButton = UIAlertAction(title: "Okay", style: .Default, handler: nil) alertController.addAction(okButton) controller.dismissViewControllerAnimated(true){ () -> Void in self.present(alertController, animated: true, completion: nil) } 

Alternatively, you can also provide alertController on top of MailComposeViewController , for example:

 let alertController = UIAlertController(title: "test", message: "test", preferredStyle: .Alert) let okButton = UIAlertAction(title: "Okay", style: .Default, handler: nil) alertController.addAction(okButton) controller.present(alertController, animated: true, completion: nil) 
+5
source

Swift 4

Do not show warning message again

In didload

 let AlertOnce = UserDefaults.standard if(!AlertOnce.bool(forKey: "oneTimeAlert")){ let messageTitle = "Your selected branch is \(storeIDName)" let alertView = UIAlertController(title: messageTitle, message: "", preferredStyle: .actionSheet) let DoNotShowAgainAction = UIAlertAction(title: "Do Not Show Again", style: UIAlertActionStyle.default) { (action:UIAlertAction) in AlertOnce.set(true , forKey: "oneTimeAlert") AlertOnce.synchronize() } let change = UIAlertAction(title: "Change Branch", style: .default){(action) in let myVC = self.storyboard?.instantiateViewController(withIdentifier: "FindRestaurentViewControllerID") as! FindRestaurentViewController self.navigationController?.pushViewController(myVC, animated: true) } alertView.addAction(DoNotShowAgainAction) alertView.addAction(change) present(alertView, animated: true,completion: nil) alertView.setValue(NSAttributedString(string: messageTitle, attributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 20),NSAttributedStringKey.foregroundColor : UIColor(red: 234/256, green: 104/256, blue: 26/256, alpha: 1)]), forKey: "attributedTitle") alertView.view.tintColor = UIColor.black } 
0
source

I needed an actionSheet, not a warning, and due to my specific circumstances, none of the solutions here worked. If your UIAlertController does not appear, an alternative way to do this is to always put it as the topmost window (in Swift 4):

 func topmostController() -> UIViewController? { if var topController = UIApplication.shared.keyWindow?.rootViewController { while let presentedViewController = topController.presentedViewController { topController = presentedViewController } return topController } return nil } // Now put up the menu let menu=UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) menu.addAction(UIAlertAction(title: "Test", style: .default, handler: {_ in self.doTest()} )) menu.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {_ in self.doCancel()} )) topmostController()?.present(menu, animated: true, completion: nil) 

This displays a window regardless of your view controller stack.

0
source

Source: https://habr.com/ru/post/1244529/


All Articles