Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Take a snapshot of view without adding it to the screen

I'm trying to load a view from a nib, configure it, and take a snapshot of it, without adding it to the screen:

+ (void)composeFromNibWithImage:(UIImage*)catImage completion:(CompletionBlock)completion {

    NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:@"CatNib" owner:nil options:nil];
    CatView *catView = [nibContents firstObject];

    //here, catView is the correct size from the nib, but is blank if inspected with the debugger

    catView.catImageView.image = catImage;
    catView.furButton.selected = YES;    
    UIImage *composite = [UIImage snapshot:catView];
    completion(composite);
}

where snapshot is the typical:

+ (UIImage *)snapshot:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

However, both catView and composite are sized correctly but blank as I step through the code. How can I create a UIImage from a view that is loaded from a nib, without adding the view to the screen?

like image 597
soleil Avatar asked Feb 13 '15 21:02

soleil


2 Answers

I had a similar issue some time ago, and as far as I can tell it is not possible to take a snapshot of a view, that is not actually on the screen. I created a workaround and placed the concerned view, which I wanted to snapshot, outside of the current ViewControllers view bounds, so that you won't see it. In this case it was possible to create a valid snapshot. Hope this helps :)

like image 122
croX Avatar answered Nov 18 '22 02:11

croX


This feels a bit hacky, but I tried it and it does get the job done. If you load the view from your nib behind the main view, you can take a screenshot of just that layer. So long as it's not a memory intensive view, the user would never know that view was added to the super view.

UIGraphicsBeginImageContext(CGSizeMake(catView.frame.size.width, catView.frame.size.height));
CGContextRef context = UIGraphicsGetCurrentContext();
[catView.layer renderInContext:context];
UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

So run this code after you load your nib behind your main view. Once it's loaded you can remove it with `[catView removeFromSuperiew]'

like image 2
timgcarlson Avatar answered Nov 18 '22 04:11

timgcarlson