I'm curious if there is a way to simplify / make a closure reusable? I asked a much more in depth question here: Swift - Refactoring code. Closure and inout? and its the same code in question.
What I'm trying to do is make this closure a single line:
self.feedbackManager?.send(on: self) { [weak self] result in
switch result {
case .failure(let error):
print("error: ", error.localizedDescription)
case .success(_):
print("Success")
}
self?.feedbackManager = nil
}
feedbackManager
is an instance of a class, which presents a MFMailComposeViewController
on the self.viewController
. The result
is the MFMailComposeResult
. Which is the result
in the closure.
So that ideally, it can be called something like this?
self.feedbackManager?.send(on: self) { switchResultClosure }
Edit: Result
Implementation:
let feedback = Feedback(subject: "subject", body: "body", footer: "footer")
sendEmail(with: feedback, on: self)
Class:
import UIKit
import MessageUI
struct Feedback {
let recipients = [R.App.Contact.email]
let subject: String
let body: String
let footer: String
}
enum SendStatus: Int {
case sent, cancelled, failed, notSupported, saved
}
protocol FeedbackProtocol {
func sendEmail(with feedback: Feedback, on viewController: UIViewController)
}
extension FeedbackProtocol {
func sendEmail(with feedback: Feedback, on viewController: UIViewController) {
print("protocol FeedbackController: sendEmail()")
ShareController.shared.sendMailToRecipients(with: feedback, on: viewController) { (SendStatus) in
print("SendStatus: ", SendStatus)
}
}
}
final class ShareController: NSObject {
static var shared = ShareController()
var completionBlock: ((SendStatus) -> Void)?
private override init() { }
}
extension ShareController: MFMailComposeViewControllerDelegate {
func sendMailToRecipients(with feedback: Feedback, on viewController: UIViewController, block: @escaping (SendStatus) -> Void) {
print("sendMailToRecipients()")
guard MFMailComposeViewController.canSendMail() else {
block(.notSupported)
return
}
var appVersion = ""
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
appVersion = version
}
completionBlock = block
let mailController = MFMailComposeViewController()
mailController.mailComposeDelegate = self
mailController.mailComposeDelegate = self
mailController.setToRecipients(feedback.recipients)
mailController.setSubject(feedback.subject)
mailController.setMessageBody((feedback.body), isHTML: true)
DispatchQueue.main.async {
viewController.present(mailController, animated: true, completion: nil)
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
print("mailComposeController(): ShareVC")
controller.dismiss(animated: true)
switch result {
case .sent: completionBlock?(.sent)
case .cancelled: completionBlock?(.cancelled)
case .failed: completionBlock?(.failed)
case .saved: completionBlock?(.saved)
default: break
}
}
}
Yes you can do by creating function with same parameter as your closure. Call below function. instead of writing closure in send just type switchResultClosure with out brackets. Syntax might not be accurate.
func switchResultClosure(result: ResultDataType) {
// switch code
switch result {
case let .failure(error):
print("error: ", error.localizedDescription)
case .success:
print("Success")
}
self?.feedbackManager = nil
}
feedbackManager?.send(on: self, switchResultClosure)