How to save screenshot of a view with its subviews in Swift?

14,319

Solution 1

This is working for me,

func screenShotMethod() {
    //Create the UIImage
    UIGraphicsBeginImageContext(faceTrackerContainerView.frame.size)
    faceTrackerContainerView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    //Save it to the camera roll
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}

Ref

Solution 2

extension UIView {
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

It makes an UIImage from a UIView. Then you can use that image with UIImageView(image:) method

Solution 3

Why not just call snapshotView(afterScreenUpdates:)?

Solution 4

It isn't very elegant, but hiding views before the screenshot is taken works. You can then make them visible afterwards.

view.isHidden = true

//screenshot

view.isHidden = false
Share:
14,319
Vinz
Author by

Vinz

Updated on June 25, 2022

Comments

  • Vinz
    Vinz almost 2 years

    I want to capture a view with its subviews. I'm using this code to capture the screen:

    let view = self.faceTrackerContainerView
    
    UIGraphicsBeginImageContext(CGSizeMake(view.bounds.size.width, view.bounds.size.height))
    UIGraphicsGetCurrentContext()!
    self.view?.drawViewHierarchyInRect(view.frame, afterScreenUpdates: true)
    let screenshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    UIImageWriteToSavedPhotosAlbum(screenshot, nil, nil, nil)
    

    These codes capture the whole screen including a button that's in front of the view. I tried these codes but it only captures the main view excluding its subviews:

    let view = self.faceTrackerContainerView
    let scale = UIScreen.mainScreen().scale
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, scale);
    
    view.layer.renderInContext(UIGraphicsGetCurrentContext()!)
    let screenshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    UIImageWriteToSavedPhotosAlbum(screenshot, nil, nil, nil)
    

    I also tried the snapshotViewAfterScreenUpdates(true) from here but I don't know how to implement it. I have a collectionView below the view and a button on top of the view (both are not in the view). The first codes capture everything with the button, collectionView, and subviews. The second codes capture the view without the subviews. What am I missing?

  • Vinz
    Vinz over 7 years
    Thanks for the codes. I'm pretty new at this. Would you mind telling me which parts I need to change/correct?
  • BaSha
    BaSha over 7 years
    @Vinz: I guess mentioned method will return UIView with rendering captured view, not direct UIImage - you want to store in PhotosAlbum
  • Vinz
    Vinz over 7 years
    Hi. Thanks for this. This is also where I got the codes and it's capturing everything in my screen. I just want to capture a view with its subview though.
  • Mohammad Zaid Pathan
    Mohammad Zaid Pathan over 7 years
    Try changing view with self.faceTrackerContainerView from above code.
  • Vinz
    Vinz over 7 years
    I've tried that but views down't have the renderInContext method though.
  • Vinz
    Vinz over 7 years
    I tried using it but can't get it to work. Gave me a blank in one of my tries.
  • Bruno Sosa Fast Tag
    Bruno Sosa Fast Tag over 2 years
    nice, work 0 problems