首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Swift 5-电子邮件类助手/经理

Swift 5-电子邮件类助手/经理
EN

Stack Overflow用户
提问于 2020-06-28 01:03:16
回答 3查看 987关注 0票数 1

编辑:

非常感谢Paulw11帮助我解决这个问题。为了便于重用,我在这里添加了完整的代码:

类:

代码语言:javascript
运行
复制
import UIKit
import MessageUI

struct Feedback {
    let recipients: [String]
    let subject: String
    let body: String
    let footer: String
}

class FeedbackManager: NSObject, MFMailComposeViewControllerDelegate {

private var feedback: Feedback

private var completion: ((Result<MFMailComposeResult,Error>)->Void)?

override init() {
    fatalError("Use FeedbackManager(feedback:)")
}

init?(feedback: Feedback) {
    guard MFMailComposeViewController.canSendMail() else {
        return nil
    }
    
    self.feedback = feedback
}

func send(on viewController: UIViewController, completion:(@escaping(Result<MFMailComposeResult,Error>)->Void)) {
    
    let mailVC = MFMailComposeViewController()
    self.completion = completion
    
    mailVC.mailComposeDelegate = self
    mailVC.setToRecipients(feedback.recipients)
    mailVC.setSubject(feedback.subject)
    mailVC.setMessageBody("<p>\(feedback.body)<br><br><br><br><br>\(feedback.footer)</p>", isHTML: true)
    
    viewController.present(mailVC, animated:true)
}

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    if let error = error {
        completion?(.failure(error))
        controller.dismiss(animated: true)
    } else {
        completion?(.success(result))
        controller.dismiss(animated: true)
    }
}
}

主计长:

添加变量:

代码语言:javascript
运行
复制
var feedbackManager: FeedbackManager?

使用:

代码语言:javascript
运行
复制
    let feedback = Feedback(recipients: "String", subject: "String", body: "Body", footer: "String")
    if let feedManager = FeedbackManager(feedback: feedback) {
        self.feedbackManager = feedManager
        self.feedbackManager?.send(on: self) { [weak self] result in
            switch result {
            case .failure(let error):
                print("error: ", error.localizedDescription)
            // Do something with the error
            case .success(let mailResult):
                print("Success")
                // Do something with the result
            }
            self?.feedbackManager = nil
        }
    } else { // Cant Send Email: // Added UI Alert:
        let failedMenu = UIAlertController(title: "String", message: nil, preferredStyle: .alert)
        let okAlert = UIAlertAction(title: "String", style: .default)
        failedMenu.addAction(okAlert)
        present(failedMenu, animated: true)
    }

我正在尝试创建一个类来处理初始化MFMailComposeViewController以在应用程序中发送电子邮件。

我有问题让它起作用。好吧,如果它不起作用,它就不会崩溃。

类:

代码语言:javascript
运行
复制
import UIKit
import MessageUI

struct Feedback {
    let recipients = "String"
    let subject: String
    let body: String
}

class FeedbackManager: MFMailComposeViewController, MFMailComposeViewControllerDelegate {
    
    func sendEmail(feedback: Feedback) {
        
        if MFMailComposeViewController.canSendMail() {
            
            self.mailComposeDelegate = self
            self.setToRecipients([feedback.recipients])
            self.setSubject("Feedback: \(feedback.subject)")
            self.setMessageBody("<p>\(feedback.body)</p>", isHTML: true)
            
        } else {
            print("else:")
            mailFailed()
        }
    }
    
    func mailFailed() {
        print("mailFailed():")
        let failedMenu = UIAlertController(title: "Please Email Me!", message: nil, preferredStyle: .alert)
        let okAlert = UIAlertAction(title: "Ok!", style: .default)
        failedMenu.addAction(okAlert)
        self.present(failedMenu, animated: true, completion: nil)
    }
    
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
    }
}

然后从不同的视图控制器调用它:

代码语言:javascript
运行
复制
  let feedbackManager = FeedbackManager()
  feedbackManager.sendEmail(feedback: Feedback(subject: "String", body: "String"))
  self.present(feedbackManager, animated: true, completion: nil)
  tableView.deselectRow(at: indexPath, animated: true)

如果MFMailComposeViewController.canSendMail() ==是真的话,上面的功能就很好了。我面临的问题是,如果canSendMail()不是真,那么类显然无法初始化和崩溃。这很有道理。

错误:

代码语言:javascript
运行
复制
Unable to initialize due to + [MFMailComposeViewController canSendMail] returns NO.

我不知道该怎么做才能解决这个问题。我尝试过将FeedbackManager从MFMailComposeViewController更改为UIViewController。这似乎是可行的,但因为它在堆栈上添加了一个视图,所以导致了一个奇怪的图形显示。

我可以做的另一件事是导入MessageUI,并为我希望能够发送电子邮件的每个控制器遵守MFMailComposeViewController。这样,在尝试初始化canSendMail()之前,我可以对照FeedbackManager()进行检查。但这似乎也不是最好的答案。

不然我该怎么做呢?

编辑:我已经让代码来处理这个问题了,但是,在显示MFMailComposeViewController之前,将视图添加到堆栈中是一个很糟糕的转变。

代码语言:javascript
运行
复制
class FeedbackManager: UIViewController, MFMailComposeViewControllerDelegate {
    
    func sendEmail(feedback: Feedback, presentingViewController: UIViewController) -> UIViewController {
        
        if MFMailComposeViewController.canSendMail() {
            
            let mail = MFMailComposeViewController()
            mail.mailComposeDelegate = self
            mail.setToRecipients([feedback.recipients])
            mail.setSubject("Feedback: \(feedback.subject)")
            mail.setMessageBody("<p>\(feedback.body)</p>", isHTML: true)
            
             present(mail, animated: true)
            return self
        } else {
            print("else:")
            return mailFailed(presentingViewController: presentingViewController)
        }
    }
    
    func mailFailed(presentingViewController: UIViewController) -> UIViewController {
        print("mailFailed():")
        let failedMenu = UIAlertController(title: "Please Email Me!", message: nil, preferredStyle: .alert)
        let okAlert = UIAlertAction(title: "Ok!", style: .default)
        failedMenu.addAction(okAlert)
        return failedMenu
    }
    
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
        self.dismiss(animated: false)
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-06-29 00:43:10

子类MFMailComposeViewController是错误的方法。这个类的意思是“原样”。如果您愿意,可以构建一个包装类:

代码语言:javascript
运行
复制
struct Feedback {
    let recipients = "String"
    let subject: String
    let body: String
}

class FeedbackManager: NSObject, MFMailComposeViewControllerDelegate {
    
    private var feedback: Feedback
    
    private var completion: ((Result<MFMailComposeResult,Error>)->Void)?
    
    override init() {
        fatalError("Use FeedbackManager(feedback:)")
    }
    
    init?(feedback: Feedback) {
        guard MFMailComposeViewController.canSendMail() else {
            return nil
        }
        
        self.feedback = feedback
    }
    
    func send(on viewController: UIViewController, completion:(@escaping(Result<MFMailComposeResult,Error>)->Void)) {
        
        let mailVC = MFMailComposeViewController()
        self.completion = completion
        
        mailVC.mailComposeDelegate = self
        mailVC.setToRecipients([feedback.recipients])
        mailVC.setSubject("Feedback: \(feedback.subject)")
        mailVC.setMessageBody("<p>\(feedback.body)</p>", isHTML: true)
        
        viewController.present(mailVC, animated:true)
    } 
    
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        if let error = error {
            completion?(.failure(error))
        } else {
            completion?(.success(result))
        }
    }
}

然后从视图控制器中使用它:

代码语言:javascript
运行
复制
let feedback = Feedback(subject: "String", body: "Body")
if let feedbackMgr = FeedbackManager(feedback: feedback) {
    self.feedbackManager = feedbackMgr
    feedback.send(on: self) { [weak self], result in 
        switch result {
            case .failure(let error):
                // Do something with the error
            case .success(let mailResult):
                // Do something with the result
        }
        self.feedbackManager = nil
    }
} else {
    // Can't send email
}

您将需要在属性中保存对FeedbackManager的强引用,否则它将在包含的函数退出时立即释放。我上面的代码引用了一个属性

代码语言:javascript
运行
复制
var feedbackManager: FeedbackManager?

虽然这样可以工作,但更好的UX是直接检查canSendMail并禁用/隐藏允许他们发送反馈的UI组件

票数 4
EN

Stack Overflow用户

发布于 2020-06-28 05:13:30

您可以按以下方式更改代码。

代码语言:javascript
运行
复制
struct Feedback {
    let recipients = "String"
    let subject: String
    let body: String
}

class FeedbackManager: NSObject, MFMailComposeViewControllerDelegate {
    
    func sendEmail(presentingViewController: UIViewController)) {
        
        if MFMailComposeViewController.canSendMail() {
            
            let mail = MFMailComposeViewController()
            mail.mailComposeDelegate = self
            mail.setToRecipients([feedback.recipients])
            mail.setSubject("Feedback: \(feedback.subject)")
            mail.setMessageBody("<p>\(feedback.body)</p>", isHTML: true)
            presentingViewController.present(mail, animated: true)
            
        } else {
            print("else:")
            mailFailed(presentingViewController: presentingViewController)
        }
    }
    
    func mailFailed(presentingViewController: UIViewController) {
        print("mailFailed():")
        let failedMenu = UIAlertController(title: "Please Email Me!", message: nil, preferredStyle: .alert)
        let okAlert = UIAlertAction(title: "Ok!", style: .default)
        failedMenu.addAction(okAlert)
        presentingViewController.present(failedMenu, animated: true, completion: nil)
    }
    
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
    }
}

现在,mailComposer可以从另一个UIViewController类打开,如下所示。

代码语言:javascript
运行
复制
let feedbackManager = FeedbackManager()
feedbackManager.sendEmail(presentingViewController: self)

希望它能帮上忙

票数 0
EN

Stack Overflow用户

发布于 2020-06-28 19:31:57

首先添加一个检查.canSendMail是否为真的类来解决这个问题。如果是的话,它就会打开邮政发送类来表示MFMailComposeViewController。

这是我提出的唯一允许MFMailComposeViewController成为自己的MFMailComposeViewControllerDelegate的解决办法。同时,如果.canSendMail = false,也可以防止崩溃。

代码语言:javascript
运行
复制
import UIKit
import MessageUI

struct Feedback {
    let recipients = ["Strings"]
    let subject: String
    let body: String
}

class FeedbackManager {

    func tryMail() -> Bool {
        if MFMailComposeViewController.canSendMail() {
            return true
        } else {
            return false
        }
    }

    func mailFailed() -> UIViewController {
        let failedMenu = UIAlertController(title: "Please Email Me!", message: nil, preferredStyle: .alert)
        let okAlert = UIAlertAction(title: "Ok!", style: .default)
        failedMenu.addAction(okAlert)
        return failedMenu
    }
}

class PostalManager: MFMailComposeViewController, MFMailComposeViewControllerDelegate {

    func sendEmail(feedback: Feedback) -> MFMailComposeViewController {
        if MFMailComposeViewController.canSendMail() {
            self.mailComposeDelegate = self
            self.setToRecipients(feedback.recipients)
            self.setSubject("Feedback: \(feedback.subject)")
            self.setMessageBody("<p>\(feedback.body)</p>", isHTML: true)
        }
        return self
    }

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
    }
}

呼叫:

代码语言:javascript
运行
复制
let feedbackManager = FeedbackManager()
let feedback = Feedback(subject: "String", body: "Body")

switch feedbackManager.tryMail() {

case true:
let postalManager = PostalManager()
present(postalManager.sendEmail(feedback: feedback), animated: true)
case false:
present(feedbackManager.mailFailed(), animated: true)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62617112

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档