-1

I'm looking to save or convert a UIView into an image which can then be emailed as an image.

I've tried :

UIGraphicsBeginImageContext(self.view.bounds.size);
    self.view.layer.render(in: UIGraphicsGetCurrentContext()!)
    let screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

but then I can't call back screenShot as it is required in a different function.

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

    mailComposerVC.setToRecipients(["emailaddress"email.com"])
    mailComposerVC.setSubject("ScreenShot")
    mailComposerVC.setMessageBody("Here's the image", isHTML: true)
    let imageData: NSData = UIImagePNGRepresentation(screenShot.image)!
    mail.addAttachmentData(imageData, mimeType: "image/png", fileName: "imageName")
    return mailComposerVC
}

I'm not sure if that would work even if it wasn't returning errors, but it's the only way I could think of.

Jon Bould
  • 65
  • 7
  • Jon, what have you tried? it's much easier for people to help if you can show a specific problem and some code that you've tried. – Wez Oct 16 '17 at 11:04
  • Looks like the code you've provided solves the problem you describe in your question. Seems like your problem is more to do with the order or execution and making sure you can use the screenshot variable in a different method, is that right? – Wez Oct 16 '17 at 11:11
  • You're probably right. I'm unsure if it's working at all because there's no difference with or without the code. And then when trying to use the variable in the `fund configureMailController` it gives an error so I can't run that either. – Jon Bould Oct 16 '17 at 11:15
  • @Wez so yes I would hope it's a matter of not being able to use the variable in a different method. – Jon Bould Oct 16 '17 at 11:17
  • Is there a reason you can't put the `UIGraphicsBeginImageContext` code inside the `configureMailController()` method to test it? – Wez Oct 16 '17 at 11:17
  • @Wez I hadn't thought of that. I'll try it, and if it works I'm going to feel very stupid. – Jon Bould Oct 16 '17 at 11:23
  • It sounds like a simple matter of variable scope. You have `let screenshot...` in one place in your code, but then you say *"...I can't call back screenShot as it is required in a different function"*. If so, there's at least two ways around this: (1) Pass `screenshot` into `configureMailController`, or (2) declare a broader scope to `screenshot`. –  Oct 16 '17 at 11:32
  • @Wez I'm not sure if you'll be able to help be with this but I may as well ask. Is it possible to adapt this code to save an image of the whole view (I.e. the whole view controller not just what can fit onto the screen at one time) – Jon Bould Oct 16 '17 at 12:15
  • @Wez I'd love to, unfortunately I don't have enough reputation to use the chat yet. Well on my profile it says I do, but on the chat it says I don't... – Jon Bould Oct 16 '17 at 12:23
  • @Wez I can go into the chat but I can't type anything because it says I don't have enough reputation – Jon Bould Oct 16 '17 at 12:31
  • Try a refresh - https://chat.stackoverflow.com/rooms/26424/iosandroidchaosoverflow – Wez Oct 16 '17 at 12:32
  • @Wez I've been trying and nothing changes – Jon Bould Oct 16 '17 at 12:33

1 Answers1

1

Turns out it does work by putting all the code inside the same function.

This is the code I used:

func configureMailController() -> MFMailComposeViewController {
    UIGraphicsBeginImageContext(self.view.bounds.size);
    self.view.layer.render(in: UIGraphicsGetCurrentContext()!)
    let screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    let mailComposerVC = MFMailComposeViewController()
    mailComposerVC.mailComposeDelegate = self

    mailComposerVC.setToRecipients(["emailaddress@email.com"])
    mailComposerVC.setSubject("Form")
    mailComposerVC.setMessageBody("Here's the image", isHTML: true)
    let imageData: NSData = UIImagePNGRepresentation(screenShot!)! as NSData
    mailComposerVC.addAttachmentData(imageData as Data, mimeType: "image/png", fileName: "imageName")
    return mailComposerVC
}
Jon Bould
  • 65
  • 7
  • 1
    Per my comment I just posted - are you "up to speed" on what variable scope is? If not, you'd do good to learn about it. The *real* issue is just that `screenshot` - which probably *should* be in it's own function - is a variable that is "out of scope" or "inaccessible" inside `configureMailController`. A better design that allows for more reusable, modular code is to break that "monster" function down into two. One that creates `screenshot` and one that takes any `UIImage` as input. –  Oct 16 '17 at 11:36
  • @dfd Thanks for your comment. You're absolutely right, I'm going to look into variable scope as that would be extremely helpful. – Jon Bould Oct 16 '17 at 11:42
  • also putting the image converting code into an extension is very helpful. as described on this post. https://stackoverflow.com/questions/30696307/how-to-convert-a-uiview-to-an-image – Jon Bould Oct 16 '17 at 12:05