Search code examples
iosswiftuigraphicscontext

Issue capturing selected views as they appear on screen with renderInContext in Swift


I have three views on my storyboard, viewA, viewB, viewC.

I’m trying to screen capture only two views as they appear on screen in their current place, viewB and viewC.

The trouble is, when I render them, the resulting image captured shows viewB and viewC in incorrect locations, the position of the views change moving top left (0, 0), see image.

How can I correct the code below so that I can capture the views viewB and viewC exactly as they are positioned on the view using the renderInContext implementation below?

UIGraphicsBeginImageContextWithOptions(self.view.frame.size, false, 0)
self.viewB.layer.renderInContext(UIGraphicsGetCurrentContext()!)
self.viewC.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

enter image description here


Solution

  • From the docs for renderInContext::

    Renders in the coordinate space of the layer.

    Each view's layer has an origin of 0,0 so they each appear in the upper-left corner.

    To fix this you need to translate the graphics context by the view's origin before calling renderInContext:.

    UIGraphicsBeginImageContextWithOptions(self.view.frame.size, false, 0)
    let ctx = UIGraphicsGetCurrentContext()
    
    CGContextSaveGState(ctx)
    CGContextTranslateCTM(ctx, self.viewB.frame.origin.x, self.viewB.frame.origin.y)
    self.viewB.layer.renderInContext(UIGraphicsGetCurrentContext()!)
    CGContextRestoreGState(ctx)
    
    CGContextSaveGState(ctx)
    CGContextTranslateCTM(ctx, self.viewC.frame.origin.x, self.viewC.frame.origin.y)
    self.viewC.layer.renderInContext(UIGraphicsGetCurrentContext()!)
    CGContextRestoreGState(ctx)
    
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()