1

I am trying to share the entire view controller as an image or a PDF. Below I have the current code I am using to share the view controller as an image but I am not sure how to modify the bounds in order to save the entire view controller, including content that is off the screen. I also do not know how to give an option to save as image or PDF.

@IBAction func shareButton(_ sender: Any) {
    let bounds = UIScreen.main.bounds
    UIGraphicsBeginImageContextWithOptions(bounds.size, true, 0.0)
    self.view.drawHierarchy(in: bounds, afterScreenUpdates: false)
    let img = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    let activityViewController = UIActivityViewController(activityItems: [img!], applicationActivities: nil)
    activityViewController.popoverPresentationController?.sourceView = self.view
    self.present(activityViewController, animated: true, completion: nil)
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Thisoneguy
  • 11
  • 2
  • I think I saw this somewhere else on stackoverflow recently. Ill look for the answer but if I remember properly, you'll want to change the `bounds.size` to the total size you need to capture, then set the point to start looking at outside of your view in order to capture all of it. – Jake Feb 26 '18 at 04:24
  • Now just to make sure, You're not trying to capture a table or collection view off screen right? Because the data doesn't load until it's on the screen if almost every case. – Jake Feb 26 '18 at 04:37
  • Yes I am trying to capture a table view that is off the screen, so it may be easier to just not use a tableview, would a scrollview allow me to capture what's off of the screen? – Thisoneguy Feb 26 '18 at 12:28
  • Yes. But if your data gets too big it will cause problems – Jake Feb 26 '18 at 13:34
  • I tried it with a scrollview but it still only captures what is on the screen, let bounds = UIScreen.main.bounds is the issue but everything I try to change it to causes errors – Thisoneguy Feb 27 '18 at 21:56
  • You need to set the bounds to the size of the `scrollview` not the `view` – Jake Feb 27 '18 at 22:01
  • Can you show the errors? – Jake Feb 27 '18 at 22:02
  • let bounds = CGRect(x: 0, y: 0, width: 375, height: 2000) And got error "Thread 1: signal SIGABRT" – Thisoneguy Feb 27 '18 at 23:26
  • How do I set the bounds to the scrollview no matter what size I actually make it? – Thisoneguy Feb 27 '18 at 23:28
  • Okay, so I finally found what I read recently. I apologize for all of the wasted time. I'm going to put it as an answer below. – Jake Feb 28 '18 at 15:05
  • Okay I found a few different answers. The edit may be what you're looking for!! – Jake Feb 28 '18 at 17:39

1 Answers1

0

EDITED: Try final answer listed at the bottom.

So to process a ScreenShot it has to be rendered in the graphics on the view. Except for when the app is using SpriteKit. You can get a good explanation here: but to surmise, the method in which you get a screenshot is by the graphicsContext. Anything not on screen is not in the context so it will not be available for a screenshot. However, graphics can be drawn outside of the view manually like with SpriteKit.

If you're using SpriteKit you can do this (answer found here) :

func getScreenshot(scene: SKScene) -> UIImage {
    let bounds = self.scene!.view?.bounds
    UIGraphicsBeginImageContextWithOptions(bounds!.size, true, UIScreen.mainScreen().scale)
    self.scene?.view!.drawViewHierarchyInRect(bounds!, afterScreenUpdates: true)
    let screenshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return screenshot;
}

let bounds = self.scene!.view?.bounds this is what I saw that led me to comment earlier.

EDIT: To draw to the context try:

EDIT: view.layer.render(in: UIGraphicsGetCurrentContext()!) found HERE or view.layer.draw(in: UIGraphicsGetCurrentContext()!) found on the same page

Jake
  • 2,126
  • 1
  • 10
  • 23