renderincontext Memory Leak if not use on Main thread

后端 未结 2 1680
天命终不由人
天命终不由人 2020-12-30 17:07

I am trying to convert my UIView into UIImage using below code.

+ (UIImage *) imageWithView:(UIView *)view{
     float scale = 1.0f;
    UIGraphicsBeginImag         


        
相关标签:
2条回答
  • 2020-12-30 18:01

    I just had this happen to me (memory leak due to renderInContext) on the main thread. I was looping over hundreds off-screen views, rendering them to UIImage objects, and saving them as PNG files. What solved the problem for me was wrapping the guts of my loop in an @autoreleasepool block:

    Broken:

    for (...) {
       ...render layer in context...
       ...save image to disk...
    }
    

    Works:

    for (...) {
       @autoreleasepool {
          ...render layer in context...
          ...save image to disk...
       }
    }
    

    Makes sense, right?

    0 讨论(0)
  • 2020-12-30 18:02

    I think that issue 1 is related to the fact that UIKit is not thread safe and its use will lead to all kinds of side effects.

    If you have performance issue like you are describing, the only path forward I see is directly using CoreGraphics (not UIKit) on a secondary thread.

    You might try something like this, as a start:

    size_t width = view.bounds.size.width;
    size_t height = view.bounds.size.height;
    
    unsigned char *imageBuffer = (unsigned char *)malloc(width*height*4);
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    
    CGContextRef imageContext =
        CGBitmapContextCreate(imageBuffer, width, height, 8, width*4, colourSpace,
                  kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
    
    CGColorSpaceRelease(colourSpace);
    
    [view.layer renderInContext:imageContext];
    
    CGImageRef outputImage = CGBitmapContextCreateImage(imageContext);
    
    CGImageRelease(outputImage);
    CGContextRelease(imageContext);
    free(imageBuffer);
    

    As you see, this is pretty more complex than the UIKit way, but it can be run on a secondary thread (provided you find a way to pass the outputImage back to your UI thread which is not shown).

    0 讨论(0)
提交回复
热议问题