Search code examples
iosswiftuiscrollviewsharescreenshot

How to share "screenshot" a entire scrollview in xcode/swift?


Can someone show me where to add frame size or bounds to capture the entire scrollview it's width is set to any and its height is 2200p. import UIKit

class ViewController: UIViewController {

@IBAction func shareButton(_ sender: Any) {

        UIGraphicsBeginImageContextWithOptions(view!.frame.size, false, 0.0)
        view!.drawHierarchy(in: view!.frame, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();

        UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)

        let activityVC = UIActivityViewController(activityItems: [image!], applicationActivities: nil)

        let vc = self.view?.window?.rootViewController

        activityVC.popoverPresentationController?.sourceView = vc?.view
        activityVC.popoverPresentationController?.sourceView = self.view
        self.present(activityVC, animated: true, completion: nil)

}

}

Thats my code, it does take a screenshot but only whats on screen and the UIActivityController comes. Not to concern about renaming it each after each press or what other apps I can share with.

I've look at other post on here and get crashes or countless errors and they are outdated to begin with.

Thank you for any help.


Solution

  • The issue you're having is because your setting your graphics context size to be the size of your view, which I'm guessing is your view controllers 'view' property which is the same size as your screen.

    I'd start by putting all my scrollview content inside a content view (just a UIView to act as a container), and put that content view inside the scrollview.

    Then I'd create a category on UIView to create an image of any UIView:

    public extension UIView {
        /**
            Captures view and subviews in an image
        */
        func snapshotViewHierarchy() -> UIImage? {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
            self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
            let copied = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return copied
        }
    }
    

    and call that function on the content view, so the content view is rendered in the context using it's own bounds instead of the frame of the viewController.view.

    // get a screenshot of just this view
    guard let snapshot = myVc.contentView.snapshotViewHierarchy() else {
        return
    }
    
    // save photo
    UIImageWriteToSavedPhotosAlbum(snapshot, nil, nil, nil)
    
    // do other stuff... etc...
    

    Here's a link to a simple demo project that snapshots a view in a scrollview that is 2200points tall and saves the view as an image to the users photo roll.

    Demo Project Github link - https://github.com/appteur/ios_scrollview_image