Swift Extension with delegation (UIViewController)












0














I need ability to send email in a number of view controllers in my app. The code is same, take three params -- recipient address, body, and subject. If Mail is configured on device, initialize MFMailComposeViewController with the view controller as delegate. If Mail is not configured, throw an error. Also set current view controller as mailComposeDelegate to listen to callbacks. How does one use Swift extension to achieve it (setting delegate in extension being the main issue)?










share|improve this question






















  • What have you tried? Please show some sample code.
    – Mike Taverne
    Nov 12 '18 at 19:45










  • Share your code
    – Satish
    Nov 12 '18 at 19:47










  • It probably isn't appropriate to use an extension in this case. You can use a common UIViewController subclass as the superclass of your view controllers and implement the common code in the superclass. Another alternative is to create a "mail sender" object that accepts closures that it invokes from the delegate methods.
    – Paulw11
    Nov 12 '18 at 19:48










  • Use completion block
    – canister_exister
    Nov 12 '18 at 19:57










  • I only tried to put the code in every view controller and implement the delegate in each of them. Same duplicate code everywhere!
    – Deepak Sharma
    Nov 13 '18 at 9:23


















0














I need ability to send email in a number of view controllers in my app. The code is same, take three params -- recipient address, body, and subject. If Mail is configured on device, initialize MFMailComposeViewController with the view controller as delegate. If Mail is not configured, throw an error. Also set current view controller as mailComposeDelegate to listen to callbacks. How does one use Swift extension to achieve it (setting delegate in extension being the main issue)?










share|improve this question






















  • What have you tried? Please show some sample code.
    – Mike Taverne
    Nov 12 '18 at 19:45










  • Share your code
    – Satish
    Nov 12 '18 at 19:47










  • It probably isn't appropriate to use an extension in this case. You can use a common UIViewController subclass as the superclass of your view controllers and implement the common code in the superclass. Another alternative is to create a "mail sender" object that accepts closures that it invokes from the delegate methods.
    – Paulw11
    Nov 12 '18 at 19:48










  • Use completion block
    – canister_exister
    Nov 12 '18 at 19:57










  • I only tried to put the code in every view controller and implement the delegate in each of them. Same duplicate code everywhere!
    – Deepak Sharma
    Nov 13 '18 at 9:23
















0












0








0







I need ability to send email in a number of view controllers in my app. The code is same, take three params -- recipient address, body, and subject. If Mail is configured on device, initialize MFMailComposeViewController with the view controller as delegate. If Mail is not configured, throw an error. Also set current view controller as mailComposeDelegate to listen to callbacks. How does one use Swift extension to achieve it (setting delegate in extension being the main issue)?










share|improve this question













I need ability to send email in a number of view controllers in my app. The code is same, take three params -- recipient address, body, and subject. If Mail is configured on device, initialize MFMailComposeViewController with the view controller as delegate. If Mail is not configured, throw an error. Also set current view controller as mailComposeDelegate to listen to callbacks. How does one use Swift extension to achieve it (setting delegate in extension being the main issue)?







ios swift uiviewcontroller swift4 swift-extensions






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 '18 at 19:27









Deepak Sharma

1,3441837




1,3441837












  • What have you tried? Please show some sample code.
    – Mike Taverne
    Nov 12 '18 at 19:45










  • Share your code
    – Satish
    Nov 12 '18 at 19:47










  • It probably isn't appropriate to use an extension in this case. You can use a common UIViewController subclass as the superclass of your view controllers and implement the common code in the superclass. Another alternative is to create a "mail sender" object that accepts closures that it invokes from the delegate methods.
    – Paulw11
    Nov 12 '18 at 19:48










  • Use completion block
    – canister_exister
    Nov 12 '18 at 19:57










  • I only tried to put the code in every view controller and implement the delegate in each of them. Same duplicate code everywhere!
    – Deepak Sharma
    Nov 13 '18 at 9:23




















  • What have you tried? Please show some sample code.
    – Mike Taverne
    Nov 12 '18 at 19:45










  • Share your code
    – Satish
    Nov 12 '18 at 19:47










  • It probably isn't appropriate to use an extension in this case. You can use a common UIViewController subclass as the superclass of your view controllers and implement the common code in the superclass. Another alternative is to create a "mail sender" object that accepts closures that it invokes from the delegate methods.
    – Paulw11
    Nov 12 '18 at 19:48










  • Use completion block
    – canister_exister
    Nov 12 '18 at 19:57










  • I only tried to put the code in every view controller and implement the delegate in each of them. Same duplicate code everywhere!
    – Deepak Sharma
    Nov 13 '18 at 9:23


















What have you tried? Please show some sample code.
– Mike Taverne
Nov 12 '18 at 19:45




What have you tried? Please show some sample code.
– Mike Taverne
Nov 12 '18 at 19:45












Share your code
– Satish
Nov 12 '18 at 19:47




Share your code
– Satish
Nov 12 '18 at 19:47












It probably isn't appropriate to use an extension in this case. You can use a common UIViewController subclass as the superclass of your view controllers and implement the common code in the superclass. Another alternative is to create a "mail sender" object that accepts closures that it invokes from the delegate methods.
– Paulw11
Nov 12 '18 at 19:48




It probably isn't appropriate to use an extension in this case. You can use a common UIViewController subclass as the superclass of your view controllers and implement the common code in the superclass. Another alternative is to create a "mail sender" object that accepts closures that it invokes from the delegate methods.
– Paulw11
Nov 12 '18 at 19:48












Use completion block
– canister_exister
Nov 12 '18 at 19:57




Use completion block
– canister_exister
Nov 12 '18 at 19:57












I only tried to put the code in every view controller and implement the delegate in each of them. Same duplicate code everywhere!
– Deepak Sharma
Nov 13 '18 at 9:23






I only tried to put the code in every view controller and implement the delegate in each of them. Same duplicate code everywhere!
– Deepak Sharma
Nov 13 '18 at 9:23














2 Answers
2






active

oldest

votes


















3














I think you should create service Class for this type of Problem so it can be reused in other Application.



class MailSender : NSObject , MFMailComposeViewControllerDelegate {
var currentController : UIViewController!
var recipient : [String]!
var message : String!
var compltion : ((String)->())?
init(from Controller:UIViewController,recipint:[String],message:String) {
currentController = Controller
self.recipient = recipint
self.message = message
}

func sendMail() {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(recipient)
mail.setMessageBody(message, isHTML: true)
currentController.present(mail, animated: true)
} else {
if compltion != nil {
compltion!("error")
}
}
}

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
if compltion != nil {
compltion!("error")
}
controller.dismiss(animated: true)
}
}


now you can send mail From All three Controller using Following Code.



let mailsender = MailSender(from: self,recipint:["example@via.com"],message:"your message")
mailsender.sendMail()
mailsender.compltion = { [weak self] result in
print(result)
//other stuff

}


remember I have used simple Clouser(completion) that take String as Argument to inform whether it is success or fails but you can write as per your requirment.in addition you can also use delegate pattern instead of clouser or callback.



main advantage of this type of service Class is dependancy injection.for more details : https://medium.com/@JoyceMatos/dependency-injection-in-swift-87c748a167be






share|improve this answer





























    0














    Create a global function:



    func sendEmail(address: String, body: String, subject: String, viewController: UIViewController) {
    //check if email is configured or throw error...
    }





    share|improve this answer





















    • And how do I handle delegate?
      – Deepak Sharma
      Nov 13 '18 at 9:24











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268831%2fswift-extension-with-delegation-uiviewcontroller%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    I think you should create service Class for this type of Problem so it can be reused in other Application.



    class MailSender : NSObject , MFMailComposeViewControllerDelegate {
    var currentController : UIViewController!
    var recipient : [String]!
    var message : String!
    var compltion : ((String)->())?
    init(from Controller:UIViewController,recipint:[String],message:String) {
    currentController = Controller
    self.recipient = recipint
    self.message = message
    }

    func sendMail() {
    if MFMailComposeViewController.canSendMail() {
    let mail = MFMailComposeViewController()
    mail.mailComposeDelegate = self
    mail.setToRecipients(recipient)
    mail.setMessageBody(message, isHTML: true)
    currentController.present(mail, animated: true)
    } else {
    if compltion != nil {
    compltion!("error")
    }
    }
    }

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    if compltion != nil {
    compltion!("error")
    }
    controller.dismiss(animated: true)
    }
    }


    now you can send mail From All three Controller using Following Code.



    let mailsender = MailSender(from: self,recipint:["example@via.com"],message:"your message")
    mailsender.sendMail()
    mailsender.compltion = { [weak self] result in
    print(result)
    //other stuff

    }


    remember I have used simple Clouser(completion) that take String as Argument to inform whether it is success or fails but you can write as per your requirment.in addition you can also use delegate pattern instead of clouser or callback.



    main advantage of this type of service Class is dependancy injection.for more details : https://medium.com/@JoyceMatos/dependency-injection-in-swift-87c748a167be






    share|improve this answer


























      3














      I think you should create service Class for this type of Problem so it can be reused in other Application.



      class MailSender : NSObject , MFMailComposeViewControllerDelegate {
      var currentController : UIViewController!
      var recipient : [String]!
      var message : String!
      var compltion : ((String)->())?
      init(from Controller:UIViewController,recipint:[String],message:String) {
      currentController = Controller
      self.recipient = recipint
      self.message = message
      }

      func sendMail() {
      if MFMailComposeViewController.canSendMail() {
      let mail = MFMailComposeViewController()
      mail.mailComposeDelegate = self
      mail.setToRecipients(recipient)
      mail.setMessageBody(message, isHTML: true)
      currentController.present(mail, animated: true)
      } else {
      if compltion != nil {
      compltion!("error")
      }
      }
      }

      func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
      if compltion != nil {
      compltion!("error")
      }
      controller.dismiss(animated: true)
      }
      }


      now you can send mail From All three Controller using Following Code.



      let mailsender = MailSender(from: self,recipint:["example@via.com"],message:"your message")
      mailsender.sendMail()
      mailsender.compltion = { [weak self] result in
      print(result)
      //other stuff

      }


      remember I have used simple Clouser(completion) that take String as Argument to inform whether it is success or fails but you can write as per your requirment.in addition you can also use delegate pattern instead of clouser or callback.



      main advantage of this type of service Class is dependancy injection.for more details : https://medium.com/@JoyceMatos/dependency-injection-in-swift-87c748a167be






      share|improve this answer
























        3












        3








        3






        I think you should create service Class for this type of Problem so it can be reused in other Application.



        class MailSender : NSObject , MFMailComposeViewControllerDelegate {
        var currentController : UIViewController!
        var recipient : [String]!
        var message : String!
        var compltion : ((String)->())?
        init(from Controller:UIViewController,recipint:[String],message:String) {
        currentController = Controller
        self.recipient = recipint
        self.message = message
        }

        func sendMail() {
        if MFMailComposeViewController.canSendMail() {
        let mail = MFMailComposeViewController()
        mail.mailComposeDelegate = self
        mail.setToRecipients(recipient)
        mail.setMessageBody(message, isHTML: true)
        currentController.present(mail, animated: true)
        } else {
        if compltion != nil {
        compltion!("error")
        }
        }
        }

        func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        if compltion != nil {
        compltion!("error")
        }
        controller.dismiss(animated: true)
        }
        }


        now you can send mail From All three Controller using Following Code.



        let mailsender = MailSender(from: self,recipint:["example@via.com"],message:"your message")
        mailsender.sendMail()
        mailsender.compltion = { [weak self] result in
        print(result)
        //other stuff

        }


        remember I have used simple Clouser(completion) that take String as Argument to inform whether it is success or fails but you can write as per your requirment.in addition you can also use delegate pattern instead of clouser or callback.



        main advantage of this type of service Class is dependancy injection.for more details : https://medium.com/@JoyceMatos/dependency-injection-in-swift-87c748a167be






        share|improve this answer












        I think you should create service Class for this type of Problem so it can be reused in other Application.



        class MailSender : NSObject , MFMailComposeViewControllerDelegate {
        var currentController : UIViewController!
        var recipient : [String]!
        var message : String!
        var compltion : ((String)->())?
        init(from Controller:UIViewController,recipint:[String],message:String) {
        currentController = Controller
        self.recipient = recipint
        self.message = message
        }

        func sendMail() {
        if MFMailComposeViewController.canSendMail() {
        let mail = MFMailComposeViewController()
        mail.mailComposeDelegate = self
        mail.setToRecipients(recipient)
        mail.setMessageBody(message, isHTML: true)
        currentController.present(mail, animated: true)
        } else {
        if compltion != nil {
        compltion!("error")
        }
        }
        }

        func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        if compltion != nil {
        compltion!("error")
        }
        controller.dismiss(animated: true)
        }
        }


        now you can send mail From All three Controller using Following Code.



        let mailsender = MailSender(from: self,recipint:["example@via.com"],message:"your message")
        mailsender.sendMail()
        mailsender.compltion = { [weak self] result in
        print(result)
        //other stuff

        }


        remember I have used simple Clouser(completion) that take String as Argument to inform whether it is success or fails but you can write as per your requirment.in addition you can also use delegate pattern instead of clouser or callback.



        main advantage of this type of service Class is dependancy injection.for more details : https://medium.com/@JoyceMatos/dependency-injection-in-swift-87c748a167be







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 24 '18 at 18:20









        Bhavesh.iosDev

        348111




        348111

























            0














            Create a global function:



            func sendEmail(address: String, body: String, subject: String, viewController: UIViewController) {
            //check if email is configured or throw error...
            }





            share|improve this answer





















            • And how do I handle delegate?
              – Deepak Sharma
              Nov 13 '18 at 9:24
















            0














            Create a global function:



            func sendEmail(address: String, body: String, subject: String, viewController: UIViewController) {
            //check if email is configured or throw error...
            }





            share|improve this answer





















            • And how do I handle delegate?
              – Deepak Sharma
              Nov 13 '18 at 9:24














            0












            0








            0






            Create a global function:



            func sendEmail(address: String, body: String, subject: String, viewController: UIViewController) {
            //check if email is configured or throw error...
            }





            share|improve this answer












            Create a global function:



            func sendEmail(address: String, body: String, subject: String, viewController: UIViewController) {
            //check if email is configured or throw error...
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 13 '18 at 5:18









            Alex Bailey

            380316




            380316












            • And how do I handle delegate?
              – Deepak Sharma
              Nov 13 '18 at 9:24


















            • And how do I handle delegate?
              – Deepak Sharma
              Nov 13 '18 at 9:24
















            And how do I handle delegate?
            – Deepak Sharma
            Nov 13 '18 at 9:24




            And how do I handle delegate?
            – Deepak Sharma
            Nov 13 '18 at 9:24


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268831%2fswift-extension-with-delegation-uiviewcontroller%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Xamarin.form Move up view when keyboard appear

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            Anylogic : not able to use stopDelay()