jammur
jammur

Reputation: 1219

Need to capture UIView into a UIImage, including all subviews

I need to capture a UIView and all it's subviews into a UIImage. The problem is that part of the view is off screen, so I can't use the screen capture function, and when I try to use the UIGraphicsGetImageFromCurrentImageContext() function, it doesn't seem to capture the subviews as well. Should it be capturing the subviews and I'm just doing something wrong? If not, is there any other way of accomplishing this?

Upvotes: 16

Views: 10918

Answers (4)

Rob Caraway
Rob Caraway

Reputation: 3926

Swift 4+ Version:

func getImage(from view:UIView) -> UIImage? {

    defer { UIGraphicsEndImageContext() }
    UIGraphicsBeginImageContextWithOptions(view.frame.size, true, UIScreen.main.scale)
    guard let context =  UIGraphicsGetCurrentContext() else { return nil }
    view.layer.render(in: context)
    return UIGraphicsGetImageFromCurrentImageContext()   

}

Upvotes: 2

Crashalot
Crashalot

Reputation: 34523

Here's a Swift 2.x version that should work if you first create an array of the UIViews to get flattened:

// Flattens <allViews> into single UIImage
func flattenViews(allViews: [UIView]) -> UIImage? {
    // Return nil if <allViews> empty
    if (allViews.isEmpty) {
        return nil
    }

    // If here, compose image out of views in <allViews>
    // Create graphics context
    UIGraphicsBeginImageContextWithOptions(UIScreen.mainScreen().bounds.size, false, UIScreen.mainScreen().scale)
    let context = UIGraphicsGetCurrentContext()
    CGContextSetInterpolationQuality(context, CGInterpolationQuality.High)

    // Draw each view into context
    for curView in allViews {
        curView.drawViewHierarchyInRect(curView.frame, afterScreenUpdates: false)
    }

    // Extract image & end context
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    // Return image
    return image
}

Upvotes: 0

Avi Shukron
Avi Shukron

Reputation: 6118

That's the right way to go:

+ (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]); 
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

This method is an extension method for UIImage class, and it will also take care of making the image looks good on any future high-resolution devices.

Upvotes: 29

tc.
tc.

Reputation: 33592

Do you mean

UIGraphicsBeginImageContext(view.bounds.size);
[view.layer drawInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

doesn't work? I'm pretty sure it ought to...

Upvotes: 2

Related Questions