MFMailComposeViewController in Swift
Asked Answered
T

5

31

This is sample code:

import UIKit
import MessageUI

class ViewController: UIViewController, MFMailComposeViewControllerDelegate {

    @IBAction func showEmail(sender : AnyObject) {
        var emailTitle = "Test Email"
        var messageBody = "This is a test email body"
        var toRecipents = ["[email protected]"]
        var mc: MFMailComposeViewController = MFMailComposeViewController()
        mc.mailComposeDelegate = self
        mc.setSubject(emailTitle)
        mc.setMessageBody(messageBody, isHTML: false)
        mc.setToRecipients(toRecipents)

        self.presentViewController(mc, animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    func mailComposeController(controller:MFMailComposeViewController, didFinishWithResult result:MFMailComposeResult, error:NSError) {
        switch result {
        case MFMailComposeResultCancelled:
            NSLog("Mail cancelled")
        case MFMailComposeResultSaved:
            NSLog("Mail saved")
        case MFMailComposeResultSent:
            NSLog("Mail sent")
        case MFMailComposeResultFailed:
            NSLog("Mail sent failure: %@", [error.localizedDescription])
        default:
            break
        }
        self.dismissViewControllerAnimated(false, completion: nil)
    }
}

In function mailComposeController I get an error on every case expression:

Could not find an overload '~=' that accepts the supplied arguments.

What am I doing wrong?

Tratner answered 19/6, 2014 at 15:58 Comment(3)
have you tried to convert the switch cases into Swift-conform? like case MFMailComposeResult.Cancelled: ect...? I could not find the reference about this enum in Swift, so my idea would rather be a question than a pure solution.Wareing
Just tried: MFMailComposeResult.Type does not have a member named 'Canceled', etc.Tratner
hint: wherever possible one should use let instead of varAcclamation
K
33

I compared MFMailComposeResult documentation on both Xcode 5 and Xcode 6. In Swift, MFMailComposeResult is a struct

struct MFMailComposeResult {
    init(_ value: CUnsignedInt) // available in iPhone 3.0
    var value: CUnsignedInt
}

with MFMailComposeResultCancelled as a constant of type MFMailComposeResult:

var MFMailComposeResultCancelled: MFMailComposeResult { get }

while it's an enum in Objective-C:

 enum MFMailComposeResult {
    MFMailComposeResultCancelled,
    MFMailComposeResultSaved,
    MFMailComposeResultSent,
    MFMailComposeResultFailed
};
typedef enum MFMailComposeResult MFMailComposeResult;   // available in iPhone 3.0

In order to make your code work, you will have to compare their values which are CUnsignedInt.

So you will have to type the following code:

func mailComposeController(controller:MFMailComposeViewController, didFinishWithResult result:MFMailComposeResult, error:NSError) {
    switch result.value {
    case MFMailComposeResultCancelled.value:
        println("Mail cancelled")
    case MFMailComposeResultSaved.value:
        println("Mail saved")
    case MFMailComposeResultSent.value:
        println("Mail sent")
    case MFMailComposeResultFailed.value:
        println("Mail sent failure: \(error.localizedDescription)")
    default:
        break
    }
    self.dismissViewControllerAnimated(false, completion: nil)
}
Kamilah answered 20/6, 2014 at 15:3 Comment(4)
When I push the button, the function showEmail is executed and appears the form for send email. If I click "Send", then everything works fine - mail is sent, then the function mailComposeController is executed. NSLog displays the label "Mail sent" and the initial screen reappears. If I'm in the dialog box of send mail, click "Cancel" button, then dialogue does not disappear, function mailComposeController does not work, two buttons - "Send" and "Cancel", becoming gray color and so it stays. What wrong?Tratner
It seems to be a bug since first beta, you can see it hereKamilah
@AudreySobgouZebaze. Your association of MFComposeResult as struct in iOS8 and enum in iOS7 is not quite correct. MFMailComposeResult is an enum in Objective-C and it is now a struct in Swift (regardless of the OS version, or SDK: iOS 7/iOS 8)... eSeem
In Swift 2.1+ use "rawValue" (UInt32) instead of "value"Mervin
A
19

in Swift 2.0 do this:

func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
        switch result.rawValue {
        case MFMailComposeResultCancelled.rawValue:
            print("Mail cancelled")
        case MFMailComposeResultSaved.rawValue:
            print("Mail saved")
        case MFMailComposeResultSent.rawValue:
            print("Mail sent")
        case MFMailComposeResultFailed.rawValue:
            print("Mail sent failure: \(error!.localizedDescription)")
        default:
            break
        }
        controller.dismissViewControllerAnimated(true, completion: nil)
    }
Acclamation answered 26/8, 2015 at 17:4 Comment(0)
D
6

In swift 3.0 -> Syntax Change

func mailComposeController(controller: MFMailComposeViewController,
                           didFinishWithResult result: MFMailComposeResult, error: NSError?) {

    switch result.rawValue {
    case MFMailComposeResult.Cancelled.rawValue:
        print("Mail cancelled")
    case MFMailComposeResult.Saved.rawValue:
        print("Mail saved")
    case MFMailComposeResult.Sent.rawValue:
        print("Mail sent")
    case MFMailComposeResult.Failed.rawValue:
        print("Mail sent failure: %@", [error!.localizedDescription])
    default:
        break
    }
    // Dismiss the mail compose view controller.
    controller.dismissViewControllerAnimated(true, completion: nil)
}
Dhar answered 21/7, 2016 at 11:32 Comment(0)
A
1

In swift 3, you can use this clear code:

 @IBAction func sendMail(_ sender: Any) {

        print(MFMailComposeViewController.canSendMail())
        if MFMailComposeViewController.canSendMail() {
            let mail = MFMailComposeViewController()
            mail.mailComposeDelegate = self
            mail.setToRecipients(["[email protected]"])
            mail.setMessageBody("<p>This is test Mail!</p>", isHTML: true)

            present(mail, animated: true)
        } else {
             let email = "[email protected]"
             if let url = URL(string: "mailto:\(email)") {
             UIApplication.shared.open(url)
             }

        }


    }

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
        switch result {
        case .cancelled:
            print("Mail cancelled")
        case .saved:
            print("Mail saved")
        case .sent:
            self.allertInfo(_title: "Mail Info", _message: "Mail is sent successfuly", _actionTitle: "OK")
            print("Mail sent")
        case .failed:
            self.allertInfo(_title: "Mail Info", _message: "Mail isn't sent.",
_actionTitle: "OK")
            print("Mail sent failure: \(error?.localizedDescription)")
        default:
            break
        }

    }

    func allertInfo(_title:String, _message:String, _actionTitle:String) {

        let alert = UIAlertController(title: _title, message: _message, preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: _actionTitle, style: UIAlertActionStyle.default, handler: nil))
        self.present(alert, animated: true, completion: nil)

    }
Absorbing answered 10/3, 2017 at 9:51 Comment(0)
P
-7

In addition to using .value, don't forget to add to break to each case statement, see Apple's official version: https://developer.apple.com/library/iOS/samplecode/MessageComposer/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010161

Precondemn answered 18/11, 2014 at 22:14 Comment(1)
Swift does not require breakTylertylosis

© 2022 - 2024 — McMap. All rights reserved.