How Do I Take a Screen Shot of a UIView?

2018-12-31 09:46发布

I am wondering how my iPhone app can take a screen shot of a specific UIView as a UIImage.

I tried this code but all I get is a blank image.

UIGraphicsBeginImageContext(CGSizeMake(320,480));
CGContextRef context = UIGraphicsGetCurrentContext();
[myUIView.layer drawInContext:context];
UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

myUIView has dimensions 320x480 an it has some sub-views. What is the correct way to do this?

15条回答
时光乱了年华
2楼-- · 2018-12-31 09:58

You need to capture the key window for a screenshot or a UIView. You can do it in Retina Resolution using UIGraphicsBeginImageContextWithOptions and set its scale parameter 0.0f. It always captures in native resolution (retina for iPhone 4 and later).

This one does a full screen screenshot (key window)

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
CGRect rect = [keyWindow bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[keyWindow.layer renderInContext:context];   
UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

This code capture a UIView in native resolution

CGRect rect = [captureView bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[captureView.layer renderInContext:context];   
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

This saves the UIImage in jpg format with 95% quality in the app's document folder if you need to do that.

NSString  *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/capturedImage.jpg"]];    
[UIImageJPEGRepresentation(capturedImage, 0.95) writeToFile:imagePath atomically:YES];
查看更多
人气声优
3楼-- · 2018-12-31 09:58

you can use following UIView category -

@implementation UIView (SnapShot)

 - (UIImage *)snapshotImage
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);        
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];        
    // old style [self.layer renderInContext:UIGraphicsGetCurrentContext()];        
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();        
    UIGraphicsEndImageContext();        
    return image;
}    
@end
查看更多
路过你的时光
4楼-- · 2018-12-31 10:00

iOS 7 has a new method that allows you to draw a view hierarchy into the current graphics context. This can be used to get an UIImage very fast.

I implemented a category method on UIView to get the view as an UIImage:

- (UIImage *)pb_takeSnapshot {
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);

    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];

    // old style [self.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

It is considerably faster then the existing renderInContext: method.

Reference: https://developer.apple.com/library/content/qa/qa1817/_index.html

UPDATE FOR SWIFT: An extension that does the same:

extension UIView {

    func pb_takeSnapshot() -> UIImage {
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale)

        drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)

        // old style: layer.renderInContext(UIGraphicsGetCurrentContext())

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

UPDATE FOR SWIFT 3

    UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)

    drawHierarchy(in: self.bounds, afterScreenUpdates: true)

    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
查看更多
余生无你
5楼-- · 2018-12-31 10:09

I think you may want renderInContext, not drawInContext. drawInContext is more a method you would override...

Note that it may not work in all views, specifically a year or so ago when I tried to use this with the live camera view it did not work.

查看更多
皆成旧梦
6楼-- · 2018-12-31 10:09

iOS7 onwards, we have below default methods :

- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates

Calling above method is faster than trying to render the contents of the current view into a bitmap image yourself.

If you want to apply a graphical effect, such as blur, to a snapshot, use the drawViewHierarchyInRect:afterScreenUpdates: method instead.

https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html

查看更多
查无此人
7楼-- · 2018-12-31 10:09

I have created usable extension for UIView to take screenshot in Swift:

extension UIView{

var screenshot: UIImage{

    UIGraphicsBeginImageContext(self.bounds.size);
    let context = UIGraphicsGetCurrentContext();
    self.layer.renderInContext(context)
    let screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return screenShot
}
}

To use it just type:

let screenshot = view.screenshot
查看更多
登录 后发表回答