Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

snapshotViewAfterScreenUpdates creating a blank image

I'm trying to create some composite UIImage objects with this code:

someImageView.image = [ImageMaker coolImage];

ImageMaker:

- (UIImage*)coolImage {
    UIView *composite = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)];
    UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"coolImage"]]; //This is a valid image - can be viewed when debugger stops here
    [composite addSubview:imgView];

    UIView *snapshotView = [composite snapshotViewAfterScreenUpdates:YES];
//at this point snapshotView is just a blank image
    UIImage *img = [self imageFromView:snapshotView];
    return img;

}

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

    return img;
}

I just get back a blank black image. How can I fix?

like image 672
soleil Avatar asked Dec 31 '25 21:12

soleil


2 Answers

Supplying YES for -snapshotViewAfterScreenUpdates: means it needs a trip back to the runloop to actually draw the image. If you supply NO, it will try immediately, but if your view is off screen or otherwise hasn't yet drawn to the screen, the snapshot will be empty.

To reliably get an image:

- (void)withCoolImage:(void (^)(UIImage *))block {
    UIView *composite = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)];
    UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"coolImage"]]; //This is a valid image - can be viewed when debugger stops here
    [composite addSubview:imgView];

    UIView *snapshotView = [composite snapshotViewAfterScreenUpdates:YES];

    // give it a chance to update the screen…
    dispatch_async(dispatch_get_main_queue(), ^
    {
        // … and now it'll be a valid snapshot in here
        if(block)
        {
            block([self imageFromView:snapshotView]);
        }
    });
}

You would use it like this:

[someObject withCoolImage:^(UIImage *image){
    [self doSomethingWithImage:image];
}];
like image 135
leftspin Avatar answered Jan 03 '26 09:01

leftspin


The snapshotted view has to be drawn to the screen for a snapshot view to not be blank. In your case, the composite view must have a superview for drawing to work.

However, you should not be using the snapshotting API for this kind of action. It is very inefficient to create a view hierarchy for the sole purpose of creating an image. Instead, use the Core Graphics API's to setup a bitmap image context, perform drawing and get back the result using UIGraphicsGetImageFromCurrentImageContext().

like image 23
Benjamin Mayo Avatar answered Jan 03 '26 11:01

Benjamin Mayo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!