Please find code below.

  1. I am creating a QRCode.
  2. Then I want to convert it to png and email as an attachment.

The line:

let imgData = UIImagePNGRepresentation(imageToEmail)

keeps giving back nil and causes the code to crash. Any help?

class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
    @IBOutlet weak var dataField: UITextField!
    @IBOutlet weak var displayCodeView: UIImageView!

    var filter:CIFilter!
    var qrImage = UIImage()

    @IBAction func generatePressed(_ sender: UIButton) {
        if let text = dataField.text {
            let data = text.data(using: .ascii, allowLossyConversion: false)

            filter = CIFilter(name: "CIQRCodeGenerator")
            filter.setValue(data, forKey: "inputMessage")

            let transform = CGAffineTransform(scaleX: 10, y: 10)

            qrImage = UIImage(ciImage: filter.outputImage!.transformed(by: transform))
            displayCodeView.image = qrImage

            let mailComposeViewController = configureMailController(imageToEmail: qrImage)
            if MFMailComposeViewController.canSendMail() {
                self.present(mailComposeViewController, animated: true, completion: nil)
            } else {
                showMailError()
            }
        }
    }

    func configureMailController(imageToEmail: UIImage) -> MFMailComposeViewController {
        let mailComposerVC = MFMailComposeViewController()
        mailComposerVC.mailComposeDelegate = self

        mailComposerVC.setToRecipients(["[email protected]"])
        mailComposerVC.setSubject("QRCode")
        let imgData = UIImagePNGRepresentation(imageToEmail)
        mailComposerVC.addAttachmentData(imgData!, mimeType: "image/png", fileName:  "qrCode.png")
        let emailBody = "<html><body><p>QR code is attached in image </p></body></html>"
        mailComposerVC.setMessageBody(emailBody, isHTML:true)

        return mailComposerVC
    }

    func showMailError() {
        let sendMailErrorAlert = UIAlertController(title: "Email error", message: "Your device could not send email", preferredStyle: .alert)
        let dismiss = UIAlertAction(title: "Ok", style: .default, handler: nil)
        sendMailErrorAlert.addAction(dismiss)
        self.present(sendMailErrorAlert, animated: true, completion: nil)
    }

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        switch result {
        case .cancelled:
            print("Mail cancelled")
            break
        case .saved:
            print("Mail saved")
            break
        case .sent:
            print("Mail sent")
            break
        case .failed:
            print("Mail failed to send")
            break

        }
        controller.dismiss(animated: true, completion: nil)
    }
}
1

There are 1 best solutions below

3
On BEST ANSWER

Add this extension to your code

extension UIImage {

/**
 Creates the UIImageJPEGRepresentation out of an UIImage
 @return Data
 */

func generatePNGRepresentation() -> Data? {

    let newImage = self.copyOriginalImage()
    let newData = UIImagePNGRepresentation(newImage)

    return newData!
}

/**
 Copies Original Image which fixes the crash for extracting Data from UIImage
 @return UIImage
 */

private func copyOriginalImage() -> UIImage {
    UIGraphicsBeginImageContext(self.size);
    self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext();

    return newImage!
    }
}

In your code,

let imgData = imageToEmail.generatePNGRepresentation()