如何从 class 邮件中关闭 MFMailComposeViewController?
How to dismiss MFMailComposeViewController from class mail?
我已将邮件功能从我的 UIviewController 中分离出来,并将它们放入 class“邮件”中。工作正常,但现在我确实无法关闭我的“MFMailComposeViewController”。未调用委托“mailComposeController”,有什么解决办法吗?
import Foundation
import MessageUI
class Mail: UIViewController, MFMailComposeViewControllerDelegate{
static func createMail2(
fromViewController:UIViewController,
recipients :String,
messageTitle:String,
messageText :String,
attachment :AnyObject?)
{
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
//mail.mailComposeDelegate = self //Cannot assign value of type 'Mail.Type' to type 'MFMailComposeViewControllerDelegate?'
mail.mailComposeDelegate? = fromViewController as! MFMailComposeViewControllerDelegate //added ? (optional)
mail.setToRecipients([recipients]) //(["mail@to.me"])
mail.setSubject(messageTitle) //("your subject text")
mail.setMessageBody(messageText, isHTML: false)
//ggf. Attachment beifügen>>>
if attachment != nil {
//attachment vorhanden, also anhängen
let attachName = "\(messageTitle).pdf"
mail.addAttachmentData(
attachment as! Data,
mimeType: "application/octet-stream", //für binäre Daten, funktioniert immer
fileName: attachName)
}//end if attachment
//<<<ggf. Attachment beifügen
// Present the view controller modally
fromViewController.present(mail, animated: true) //show mail
} else {
// show failure alert
print("Mail services are not available")
let alert = UIAlertController(title: "Mail error", message: "Your device has not been configured to send e-mails", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(okAction)
fromViewController.present(alert,animated: true, completion: nil)
}//end if else
}//end func createMail
//mail delegate
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
//It’s called when the user dismisses the controller, either by sending the email or canceling the action. Either way, you have to dismiss the controller manually.
//ggf. noch aktionen...
controller.dismiss(animated: true) //remove the mail view
}//end func mailComposeController
}//end class Mail
您作为 fromViewController
的参数传递的 UIViewController
应该符合 MFMailComposeViewControllerDelegate
协议并且您应该在该控制器的定义中实现 mailComposeController(_: didFinishWith:
.
class Mail: UIViewController {
static func createMail2(
fromViewController: UIViewController,
recipients :String,
messageTitle:String,
messageText :String,
attachment :AnyObject?) {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
if let fromViewController = fromViewController as? MFMailComposeViewControllerDelegate {
mail.mailComposeDelegate = fromViewController
} else {
print("fromViewController needs to conform to MFMailComposeViewControllerDelegate")
}
//...
}
}
}
您需要创建邮件控制器的静态共享实例并将 if 设置为 mailComposeDelegate。您还应该在邮件控制器中创建一个控制器 属性 以保留对调用邮件编辑器的视图控制器的引用,并将您的 createMail 声明为实例方法(非静态):
import UIKit
import MessageUI
class MailComposer: NSObject, MFMailComposeViewControllerDelegate {
static let shared = MailComposer()
private var controller: UIViewController?
func compose(controller: UIViewController, recipients: String,
messageTitle: String, messageText: String, fileURL: URL? = nil) { //, completion: @escaping ((MFMailComposeResult, Error?) -> Void)) {
self.controller = controller
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = MailComposer.shared
mail.setToRecipients([recipients])
mail.setSubject(messageTitle)
mail.setMessageBody(messageText, isHTML: false)
if let fileURL = fileURL {
do {
try mail.addAttachmentData(Data(contentsOf: fileURL), mimeType: "application/octet-stream", fileName: fileURL.lastPathComponent)
} catch {
print(error)
}
}
controller.present(mail, animated: true)
} else {
let alertController = UIAlertController(title: "Mail Compose Error",
message: "Your device has not been configured to send e-mails",
preferredStyle: .alert)
alertController.addAction(.init(title: "OK", style: .default) { _ in
alertController.dismiss(animated: true)
})
controller.present(alertController, animated: true)
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
// You should switch the result only after dismissing the controller
controller.dismiss(animated: true) {
let message: String
switch result {
case .sent: message = "Message successfully sent!"
case .saved: message = "Message saved!"
case .cancelled: message = "Message Canceled!"
case .failed: message = "Unknown Error!"
@unknown default: fatalError()
}
let alertController = UIAlertController(title: "Mail Composer",
message: message,
preferredStyle: .alert)
alertController.addAction(.init(title: "OK", style: .default) { _ in
alertController.dismiss(animated: true)
})
self.controller?.present(alertController, animated: true) {
self.controller = nil
}
}
}
}
用法:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let recipients = "user@email.com"
let messageTitle = "New Message"
let messageText = "Mail Test"
MailComposer.shared.compose(controller: self, recipients: recipients, messageTitle: messageTitle, messageText: messageText)
}
}
我已将邮件功能从我的 UIviewController 中分离出来,并将它们放入 class“邮件”中。工作正常,但现在我确实无法关闭我的“MFMailComposeViewController”。未调用委托“mailComposeController”,有什么解决办法吗?
import Foundation
import MessageUI
class Mail: UIViewController, MFMailComposeViewControllerDelegate{
static func createMail2(
fromViewController:UIViewController,
recipients :String,
messageTitle:String,
messageText :String,
attachment :AnyObject?)
{
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
//mail.mailComposeDelegate = self //Cannot assign value of type 'Mail.Type' to type 'MFMailComposeViewControllerDelegate?'
mail.mailComposeDelegate? = fromViewController as! MFMailComposeViewControllerDelegate //added ? (optional)
mail.setToRecipients([recipients]) //(["mail@to.me"])
mail.setSubject(messageTitle) //("your subject text")
mail.setMessageBody(messageText, isHTML: false)
//ggf. Attachment beifügen>>>
if attachment != nil {
//attachment vorhanden, also anhängen
let attachName = "\(messageTitle).pdf"
mail.addAttachmentData(
attachment as! Data,
mimeType: "application/octet-stream", //für binäre Daten, funktioniert immer
fileName: attachName)
}//end if attachment
//<<<ggf. Attachment beifügen
// Present the view controller modally
fromViewController.present(mail, animated: true) //show mail
} else {
// show failure alert
print("Mail services are not available")
let alert = UIAlertController(title: "Mail error", message: "Your device has not been configured to send e-mails", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(okAction)
fromViewController.present(alert,animated: true, completion: nil)
}//end if else
}//end func createMail
//mail delegate
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
//It’s called when the user dismisses the controller, either by sending the email or canceling the action. Either way, you have to dismiss the controller manually.
//ggf. noch aktionen...
controller.dismiss(animated: true) //remove the mail view
}//end func mailComposeController
}//end class Mail
您作为 fromViewController
的参数传递的 UIViewController
应该符合 MFMailComposeViewControllerDelegate
协议并且您应该在该控制器的定义中实现 mailComposeController(_: didFinishWith:
.
class Mail: UIViewController {
static func createMail2(
fromViewController: UIViewController,
recipients :String,
messageTitle:String,
messageText :String,
attachment :AnyObject?) {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
if let fromViewController = fromViewController as? MFMailComposeViewControllerDelegate {
mail.mailComposeDelegate = fromViewController
} else {
print("fromViewController needs to conform to MFMailComposeViewControllerDelegate")
}
//...
}
}
}
您需要创建邮件控制器的静态共享实例并将 if 设置为 mailComposeDelegate。您还应该在邮件控制器中创建一个控制器 属性 以保留对调用邮件编辑器的视图控制器的引用,并将您的 createMail 声明为实例方法(非静态):
import UIKit
import MessageUI
class MailComposer: NSObject, MFMailComposeViewControllerDelegate {
static let shared = MailComposer()
private var controller: UIViewController?
func compose(controller: UIViewController, recipients: String,
messageTitle: String, messageText: String, fileURL: URL? = nil) { //, completion: @escaping ((MFMailComposeResult, Error?) -> Void)) {
self.controller = controller
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = MailComposer.shared
mail.setToRecipients([recipients])
mail.setSubject(messageTitle)
mail.setMessageBody(messageText, isHTML: false)
if let fileURL = fileURL {
do {
try mail.addAttachmentData(Data(contentsOf: fileURL), mimeType: "application/octet-stream", fileName: fileURL.lastPathComponent)
} catch {
print(error)
}
}
controller.present(mail, animated: true)
} else {
let alertController = UIAlertController(title: "Mail Compose Error",
message: "Your device has not been configured to send e-mails",
preferredStyle: .alert)
alertController.addAction(.init(title: "OK", style: .default) { _ in
alertController.dismiss(animated: true)
})
controller.present(alertController, animated: true)
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
// You should switch the result only after dismissing the controller
controller.dismiss(animated: true) {
let message: String
switch result {
case .sent: message = "Message successfully sent!"
case .saved: message = "Message saved!"
case .cancelled: message = "Message Canceled!"
case .failed: message = "Unknown Error!"
@unknown default: fatalError()
}
let alertController = UIAlertController(title: "Mail Composer",
message: message,
preferredStyle: .alert)
alertController.addAction(.init(title: "OK", style: .default) { _ in
alertController.dismiss(animated: true)
})
self.controller?.present(alertController, animated: true) {
self.controller = nil
}
}
}
}
用法:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let recipients = "user@email.com"
let messageTitle = "New Message"
let messageText = "Mail Test"
MailComposer.shared.compose(controller: self, recipients: recipients, messageTitle: messageTitle, messageText: messageText)
}
}