简体   繁体   English

UIAlertController 不会显示 - 在 Swift 中

[英]UIAlertController won't display - In Swift

I have created a ContactUsViewController .我创建了一个ContactUsViewController

In this controller the user will select a option from a pickerView and then type a message in a textView and press the Send Email button.在该控制器中的用户将选择从一个选项pickerView然后键入一个消息textView并按下发送电子邮件按钮。

When they press the button, it creates a MFMailComposeViewController so they can send the email.当他们按下按钮时,它会创建一个MFMailComposeViewController以便他们可以发送电子邮件。 Now, when the email is either Sent, Saved, Cancelled or Failed, the MFMailComposeViewController closes as they are back in my app.现在,当电子邮件发送、保存、取消或失败时, MFMailComposeViewController关闭,因为它们回到我的应用程序中。 I want an alert to then appear to give them an update, on what ever just happened.我想要一个警报,然后出现向他们提供有关刚刚发生的事情的最新信息。 I have originally set this up using a UIAlertView, and have placed this code in the fun mailComposeController function, see below:我最初使用 UIAlertView 进行设置,并将此代码放置在fun mailComposeController函数中,如下所示:

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 have used the UIAlertView for Email Saved and Email failed.如您所见,我已将UIAlertView用于电子邮件保存和电子邮件失败。 This works absolutely fine, and shows my alert as expected.这绝对可以正常工作,并按预期显示我的警报。

I recently read that UIAlertView is depreciated since iOS 8, and that we should now use UIAlertController .我最近读到UIAlertView从 iOS 8 开始贬值了,我们现在应该使用UIAlertController Therefore I tried creating the same thing using the UIAlertController , which you can see for the Email Sent section.因此,我尝试使用UIAlertController创建相同的UIAlertController ,您可以在 Email Sent 部分看到它。 However, this doesn't seem to work, it just doesn't show any alert.但是,这似乎不起作用,它只是没有显示任何警报。 It does print this error into the logs:它确实将此错误打印到日志中:

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

But I'm not really sure what this is saying, or more importantly, how to fix it.但我不确定这是什么意思,或者更重要的是,我不确定如何解决它。

My questions are:我的问题是:

  1. Am I right in saying I cannot use UIAlertView ?我说我不能使用UIAlertView吗?
  2. How can I fix this and make the UIAlerController appear after I have returned from the Mail app?从邮件应用程序返回后,如何解决此问题并使UIAlerController出现?

Thanks in advance.提前致谢。

The problem is that by the time you call this following function:问题是,当您调用以下函数时:

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

your mail view controller is still visible.您的邮件视图控制器仍然可见。 You have to make sure that the alertController is presented on the top of window hierarchy.您必须确保alertController显示在窗口层次结构的顶部。 In your example, you have the following window hierarchy:在您的示例中,您具有以下窗口层次结构:

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

What you should do instead is to dismiss the email view controller first.你应该做的是首先关闭电子邮件视图控制器。 When that is done, show you alert view 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 present your alertController on top of the MailComposeViewController , like so:或者,您也可以在alertController之上显示您的MailComposeViewController ,如下所示:

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)

I needed an actionSheet rather than an alert, and due to my specific circumstances, none of the solutions here worked.我需要一个 actionSheet 而不是警报,并且由于我的具体情况,这里的解决方案都不起作用。 If your UIAlertController isn't showing, an alternative way to do this is to always put it as the topmost window (in Swift 4):如果您的 UIAlertController 未显示,另一种方法是始终将其作为最顶部的窗口(在 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 the window regardless of your view controller stack.无论您的视图控制器堆栈如何,这都会显示窗口。

在 DispachQueue.main.async{} 中显示警报后,我现在面临同样的问题,代码工作正常。

Swift 4斯威夫特 4

Do Not Show Again Alert message不再显示警报消息

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

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM