简体   繁体   中英

How can I take a snapshot of a UIView that isn't rendered?

I use this method for taking a snapshot:

UIView *snapshotView = [someView snapshotAfterScreenUpdates:NO];

This gives me a UIView that I can play with.

But, I need the UIImage of it and not the UIView.

This is the method I use for converting a UIView to an UIImage:

- (UIImage *)snapshotOfView:(UIView *)view
{
    UIImage *snapshot;

    UIGraphicsBeginImageContext(view.frame.size);

    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    snapshot = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return snapshot;
}

It doesn't work, the snapshot is a blank UIImage because the snapshotView isn't rendered.

The obvious thing to do is to directly take a snapshot of the view instead of taking the snapshot in the form of a UIView and then converting it.

The problem with the obvious method is that I'm using a WKWebView that has a huge bug that doesn't allow you to take screenshots. And that's true, I even reported the bug and they said they are trying to fix it.

So, how can I take the snapshot (UIImage) of the snapshotView without rendering it?

drawViewHierarchyInRect will work for you. You can use this directly on your WKWebView.

There is some useful detail on this Apple Technical Q&A . Also I touch on it here in answer to a slightly different question.

I use it in a category on UIView:

@implementation UIView (ImageSnapshot)
- (UIImage*)imageSnapshot {
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, 
                                    YES, self.contentScaleFactor);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}
@end

I don't know what you mean by 'the obvious method' - but I have tested this on a WKWebView and it works.

Since accepter answer didn't worked for me ( UIGraphicsGetImageFromCurrentImageContext() returned nil all the time) I found different solution for iOS10+:

let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let image = renderer.image { _ in view.drawHierarchy(in: view.bounds, afterScreenUpdates: true) }

PS You may want to call updateConstraintsIfNeeded() and layoutIfNeeded() before rendering

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM