Search code examples
iosswiftcore-animationcalayerios-keyboard-extension

Core animation using too much memory after I set contentsScale on custom CALayer


I am using a custom CALayer to draw some UI for a keyboard extension and I am noticing a huge amount of memory usage from CoreAnimation after I add the line

self.contentsScale = UIScreen.mainScreen().scale

The total memory usage from core animation objects jumps from 4 MB across my whole app to up to 15MB. I saw this by profiling on my device and seeing the memory usage.

This causes my extension to crash on a 6+

This holds true even if I am not actually drawing anything. I've taken everything out of the drawInContext it still repros.

override func drawInContext(context: CGContext) 
{            
}

The layer does span across my whole keyboard as there are ui elements that I want to draw at different point, and I need to set the content scale because I wanted to draw some text in the layer and without the scale it looks all blurry.

Does anyone know how to reduce the memory footprint for this?

This only is a problem on iphone 6 plus


Solution

  • An empty drawInContext: implementation still causes allocations because, like -[UIView drawRect:] method, overriding this method tells iOS that you want to do custom drawing, which requires that a backing store be allocated to store the results of the layer's drawing.

    The size of this data in memory, assuming that there are no clever optimizations made, would be at least width of the keyboard * height of the keyboard * screen scale * color components per pixel * sizeof(CGFloat), or 375 * 216 * 3 * 4 * 8 = ~7mb for a keyboard the same size as the stock keyboard on the 64-bit iPhone 6+.

    It's worth noting that overriding drawInContext: or drawRect: should be avoided unless there is no other option. Unless you have some special text effect in mind that you know can't be achieved without bespoke drawing code, iOS offers many options that are both easier to use and higher performance, such as UILabel, CATextLayer, or even properly prepared CAShapeLayers.