27

Is it possible to get a UIImage from a UIView created with snapshotViewAfterScreenUpdates?

A UIView returned from snapshotViewAfterScreenUpdates looks fine when added as a subview, but the following produces a black image:

UIView *snapshotView = [someView snapshotViewAfterScreenUpdates:YES]; 
UIImage *snapshotImage = [self imageFromView:snapshotView]; 

- (UIImage *)imageFromView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0.0);
    // [view.layer renderInContext:UIGraphicsGetCurrentContext()]; // <- same result...
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return img;
}

It is of course possible to get the image without relying on snapshotViewAfterScreenUpdates:

UIImage *snapshotImage = [self imageFromView:someView];

Unfortunately, when capturing a complex view, drawViewHierarchyInRect can't match the speed of snapshotViewAfterScreenUpdates. I was hoping that it would be faster to get the UIImage from a view created by snapshotViewAfterScreenUpdates, is this possible?

carton
  • 1,020
  • 1
  • 8
  • 17

1 Answers1

21

The answer seems to be NO and Apple's documentation implicitly confirms this:

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

It's worth noting that the Implementing Engaging UI on iOS session from WWDC13 lists snapshotViewAfterScreenUpdates as the fastest method, but uses drawViewHierarchyInRect in the example code.

carton
  • 1,020
  • 1
  • 8
  • 17
  • 2
    I think the reason this is not working is that the view returned by snapshot is actually NOT a full fledged view. If you step through the debugger, you will see that it's type is '_UIReplicantView'. This makes me think that it is just an optimized copy of the other view and doesn't have the same 'layer' characteristics of a 'full' UIView... – MobileVet Nov 26 '13 at 16:27
  • 1
    Thanks @MobileVet, that's good to know. Still frustrating that there's no way to get the pixels from a feature that is all about quick screen capture... – carton Nov 27 '13 at 20:55
  • 1
    Apple confirms that this is not possible. See: http://www.raywenderlich.com/forums/viewtopic.php?f=37&t=8993&start=10 – Carlos Guzman Jun 11 '14 at 06:48
  • @CarlosGuzman thanks for adding that link, it contains some helpful explanations. – carton Jun 11 '14 at 20:24
  • Very frustrating. drawViewHierarchyInRect is too slow and uses too much CPU. You'd think there'd be a simple way to get an OpenGL texture or at least a CVPixelBufferRef from a view since it's all OpenGL underneath anyway... – jjxtra Feb 04 '15 at 04:56