Search code examples
iosswiftswitch-statementsmsmfmessagecomposeviewcontroller

In App SMS With Attachment - MFMessageComposeViewControllerDelegate Related Errors


I have the following code that takes a partial snapshot of my screen in-app, then opens up a SMS dialogue window.

import UIKit
import MessageUI
import AVFoundation


class ViewController: UIViewController, MFMailComposeViewControllerDelegate
{


@IBAction func smsScreenShot(sender: AnyObject) {

    audioPlayer.play()

    // Declare the snapshot boundaries 
    let top: CGFloat = 100
    let bottom: CGFloat = 60

    // The size of the cropped image
    let size = CGSize(width: view.frame.size.width, height: view.frame.size.height - top - bottom)

    // Start the context
    UIGraphicsBeginImageContext(size)
    CGContextTranslateCTM(context, 0, -top)

    // Draw the view into the context (this is the snapshot)
    view.layer.renderInContext(context)
    let snapshot = UIGraphicsGetImageFromCurrentImageContext()

    // End the context (this is required to not leak resources)
    UIGraphicsEndImageContext()

    // Composing the SMS

    if !MFMessageComposeViewController.canSendText() {
        print("SMS services are not available")
    }

    if (MFMessageComposeViewController.canSendText()) {

        let composeVC = MFMessageComposeViewController()

        composeVC.recipients = ["Enter tel no"]
        composeVC.body = "Have a look at this cool image!";

        // Attaching the image to the SMS.
        let image = snapshot
        let imageData = UIImagePNGRepresentation(image)
        composeVC.addAttachmentData(imageData!, typeIdentifier: "image/png", filename:"myImage")

        self.presentViewController(composeVC, animated:true, completion:nil)

    }

}

I realise I have to add MFMessageComposeViewControllerDelegate in the class construct just after 'MFMailComposeViewControllerDelegate'.

In doing so, I receive the following error:

Type 'ViewController' does not conform to protocol 'MFMessageComposeViewControllerDelegate'

And this is because I haven't dismissed the controller.

To dismiss the MFMMessageComposeViewController, I added the following code:

func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) {

switch result.value {
case MessageComposeResultCancelled.value:
    NSLog("cancelled")
case MessageComposeResultFailed.value:
    NSLog("cancelled")
case MessageComposeResultSent.value:
    NSLog("cancelled")
default:
    NSLog("default...")
}
controller.dismissViewControllerAnimated(true, completion: nil)
}

And I inserted this code just after:

self.presentViewController(composeVC, animated:true, completion:nil)

But now I am presented with the same Type 'ViewController' does not conform to protocol 'MFMessageComposeViewControllerDelegate' error as well as errors in the switch statement.

Switch Statement Errors

Firstly, I had an error using result.value so I changed it to result.rawValue. That seemed to solve that error.

But I now have errors in the case statements: Value of type 'MessageComposeResult' has no member 'value'. I think this is because the syntax surrounding MessageComposeResult is outdated or wrong?

How can I fix my case statements? I guess if I fix the case statements, all my problems will be resolved?

I have spent hours scouring similar questions and material on the Web, but am really stumped here.

Could someone please tell me where I am going wrong? And how to amend my code?

Many thanks.

Amended Code

import UIKit
import MessageUI
import AVFoundation


    class ViewController: UIViewController, MFMailComposeViewControllerDelegate, MFMessageComposeViewControllerDelegate {

   // Composing the SMS

    if !MFMessageComposeViewController.canSendText() {
        print("SMS services are not available")
    }

    if (MFMessageComposeViewController.canSendText()) {


        let composeVC = MFMessageComposeViewController()


        composeVC.recipients = ["Enter tel no"]
        composeVC.body = "Have a look at this cool image!";
        composeVC.messageComposeDelegate = self;

        // Attaching the image to the SMS.

        let image = snapshot
        let imageData = UIImagePNGRepresentation(image)
        composeVC.addAttachmentData(imageData!, typeIdentifier: "image/png", filename:"myImage")



        self.presentViewController(composeVC, animated:true, completion:nil)

        func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) {
            switch result {
            case MessageComposeResultCancelled:
                NSLog("Cancelled")

            case MessageComposeResultFailed:
                NSLog("Failed")

            case MessageComposeResultSent:
                NSLog("Sent")

            default:
                NSLog("Unknown result")

            }

        }

Solution

  • Your problem is that you are using an MFMessageComposeViewController but you have said that your class is an MFMailComposeViewControllerDelegate - Message vs Mail. You have implemented the delegate method for the MFMessageComposeViewController, which doesn't match the declaration for your class, so you get the error.

    You want

    class ViewController: UIViewController, MFMessageComposeViewControllerDelegate
    

    and then

    func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) {
        switch result {
        case MessageComposeResultCancelled:
            NSLog("Cancelled")
    
        case MessageComposeResultFailed:
            NSLog("Failed")
    
        case MessageComposeResultSent:
            NSLog("Sent")
    
        default:
            NSLog("Unknown result")
    
        }
    
    }
    

    Also, you haven't set your view controller as the delegate, so the delegate method won't be invoked:

    let composeVC = MFMessageComposeViewController()
    composeVC.messageComposeDelegate=self