iosswiftmemorycore-graphicscglayer

Ever increasing memory usage with bitmap CGContext drawing


I am trying to move a sub-area contents within a CGLayer. The main idea is that I first draw the source area (the part I want to move) into a newly created bitmap CGContext, then make a CGImage from it, and draw it back to the original layer at a different location. Here is the code snippet in question:

    let size = src.size

    //create the bitmap context
    UIGraphicsBeginImageContextWithOptions(size, true, 0)
    guard let ctx = UIGraphicsGetCurrentContext() else { return }
    ctx.saveGState()

    //flip the context to match the origin position of UIKit
    ctx.translateBy(x: 0, y: size.height)
    ctx.scaleBy(x: 1.0, y: -1.0)

    //draw the source part of the layer into the bitmap context
    let offset = CGPoint(x: -src.origin.x, y: -src.origin.y)
    let iRect = CGRect(origin: offset, size: self.shellBounds.size)
    let bounds = CGRect(origin: .zero, size: size)
    ctx.clip(to: bounds)
    ctx.draw(layer, in: iRect)

    //make a CGImage of the contents
    let image = ctx.makeImage()!

    //draw this part back to the layer (context is obtained from layer)
    context.saveGState()
    context.clip(to: target)
    context.setBlendMode(.copy)
    context.draw(image, in: target)
    context.restoreGState()
    ctx.restoreGState()
    UIGraphicsEndImageContext()

This works as expected. However, the problem is, the memory usage keeps increasing every time it is called.

The memory increase is probably because of the making of image. But it seems not released at the end. What is wrong with my code snippet? Do I need to release the created image manually? If so, how can I do that since Swift uses ARC for Core Graphics as said in documentation?


Solution

  • It turns out the memory problem starts when drawing the generated image into the layer again (when the part which draws the generated image back to the layer is commented out, the memory never increase again).

    Since the internal implementation of CGLayer is unknown, it is difficult to know the exact cause of this problem. What I did was only to give up this method and implement it in another way.