UIAlertController 不会显示 - 在 Swift
UIAlertController won't display - In Swift
我创建了一个 ContactUsViewController
。
在此控制器中,用户将从 pickerView
中 select 一个选项,然后在 textView
中键入一条消息,然后按“发送电子邮件”按钮。
当他们按下按钮时,它会创建一个 MFMailComposeViewController
以便他们可以发送电子邮件。现在,当电子邮件发送、保存、取消或失败时,MFMailComposeViewController
关闭,因为它们返回到我的应用程序中。我想要一个警报,然后显示给他们更新,关于刚刚发生的事情。我最初使用 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
}
如您所见,我已将 UIAlertView
用于电子邮件已保存和电子邮件失败。 这绝对可以正常工作,并按预期显示我的警报。
我最近读到 UIAlertView
从 iOS 8 开始贬值,我们现在应该使用 UIAlertController
。因此,我尝试使用 UIAlertController
创建相同的东西,您可以在“电子邮件已发送”部分看到它。但是,这似乎不起作用,它只是不显示任何警报。它确实将此错误打印到日志中:
Warning: Attempt to present <UIAlertController: 0x126c50d30> on <XXXX.ContactUsViewController: 0x1269cda70> whose view is not in the window hierarchy!
但我不太确定这是什么意思,或者更重要的是,我不确定如何修复它。
我的问题是:
- 我说我不能使用
UIAlertView
对吗?
- 如何解决此问题并使
UIAlerController
在我从邮件应用程序返回后出现?
提前致谢。
问题是当您调用以下函数时:
present(alertController, animated: true, completion: nil)
您的邮件视图控制器仍然可见。您必须确保 alertController
显示在 window 层次结构的顶部。在您的示例中,您具有以下 window 层次结构:
+---------------------------+
| MailComposeViewController |
+---------------------------+
||
+---------------------------+
| ContactUsViewController |
+---------------------------+
您应该先关闭电子邮件视图控制器。完成后,向您显示警报视图控制器。
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)
}
或者,您也可以在 MailComposeViewController
之上展示您的 alertController
,如下所示:
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)
Swift 4
不再显示警告消息
在 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
}
我需要一个 actionSheet 而不是一个警报,并且由于我的具体情况,none 这里的解决方案有效。如果您的 UIAlertController 未显示,另一种方法是始终将其置于最顶层 window(在 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)
无论您的视图控制器堆栈如何,这都会显示 window。
在 DispachQueue.main.async{} 中显示警报后,我现在遇到了同样的问题,代码工作正常。
我创建了一个 ContactUsViewController
。
在此控制器中,用户将从 pickerView
中 select 一个选项,然后在 textView
中键入一条消息,然后按“发送电子邮件”按钮。
当他们按下按钮时,它会创建一个 MFMailComposeViewController
以便他们可以发送电子邮件。现在,当电子邮件发送、保存、取消或失败时,MFMailComposeViewController
关闭,因为它们返回到我的应用程序中。我想要一个警报,然后显示给他们更新,关于刚刚发生的事情。我最初使用 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
}
如您所见,我已将 UIAlertView
用于电子邮件已保存和电子邮件失败。 这绝对可以正常工作,并按预期显示我的警报。
我最近读到 UIAlertView
从 iOS 8 开始贬值,我们现在应该使用 UIAlertController
。因此,我尝试使用 UIAlertController
创建相同的东西,您可以在“电子邮件已发送”部分看到它。但是,这似乎不起作用,它只是不显示任何警报。它确实将此错误打印到日志中:
Warning: Attempt to present <UIAlertController: 0x126c50d30> on <XXXX.ContactUsViewController: 0x1269cda70> whose view is not in the window hierarchy!
但我不太确定这是什么意思,或者更重要的是,我不确定如何修复它。
我的问题是:
- 我说我不能使用
UIAlertView
对吗? - 如何解决此问题并使
UIAlerController
在我从邮件应用程序返回后出现?
提前致谢。
问题是当您调用以下函数时:
present(alertController, animated: true, completion: nil)
您的邮件视图控制器仍然可见。您必须确保 alertController
显示在 window 层次结构的顶部。在您的示例中,您具有以下 window 层次结构:
+---------------------------+
| MailComposeViewController |
+---------------------------+
||
+---------------------------+
| ContactUsViewController |
+---------------------------+
您应该先关闭电子邮件视图控制器。完成后,向您显示警报视图控制器。
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)
}
或者,您也可以在 MailComposeViewController
之上展示您的 alertController
,如下所示:
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)
Swift 4
不再显示警告消息
在 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
}
我需要一个 actionSheet 而不是一个警报,并且由于我的具体情况,none 这里的解决方案有效。如果您的 UIAlertController 未显示,另一种方法是始终将其置于最顶层 window(在 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)
无论您的视图控制器堆栈如何,这都会显示 window。
在 DispachQueue.main.async{} 中显示警报后,我现在遇到了同样的问题,代码工作正常。