为什么SDWebImage在decodeImageWithImage方法中使用@autoreleasepool块?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么SDWebImage在decodeImageWithImage方法中使用@autoreleasepool块?相关的知识,希望对你有一定的参考价值。

看起来像下面的代码片段,它在此方法中使用@autoreleasepool块。

 + (UIImage *)decodedImageWithImage:(UIImage *)image {
    // while downloading huge amount of images
    // autorelease the bitmap context
    // and all vars to help system to free memory
    // when there are memory warning.
    // on ios7, do not forget to call
    // [[SDImageCache sharedImageCache] clearMemory];

    if (image == nil) { // Prevent "CGBitmapContextCreateImage: invalid context 0x0" error
        return nil;
    }

    @autoreleasepool{
        // do not decode animated images
        if (image.images != nil) {
            return image;
        }

        CGImageRef imageRef = image.CGImage;

        CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
        BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
                         alpha == kCGImageAlphaLast ||
                         alpha == kCGImageAlphaPremultipliedFirst ||
                         alpha == kCGImageAlphaPremultipliedLast);
        if (anyAlpha) {
            return image;
        }

        // current
        CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(imageRef));
        CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(imageRef);

        BOOL unsupportedColorSpace = (imageColorSpaceModel == kCGColorSpaceModelUnknown ||
                                      imageColorSpaceModel == kCGColorSpaceModelMonochrome ||
                                      imageColorSpaceModel == kCGColorSpaceModelCMYK ||
                                      imageColorSpaceModel == kCGColorSpaceModelIndexed);
        if (unsupportedColorSpace) {
            colorspaceRef = CGColorSpaceCreateDeviceRGB();
        }

        size_t width = CGImageGetWidth(imageRef);
        size_t height = CGImageGetHeight(imageRef);
        NSUInteger bytesPerPixel = 4;
        NSUInteger bytesPerRow = bytesPerPixel * width;
        NSUInteger bitsPerComponent = 8;


        // kCGImageAlphaNone is not supported in CGBitmapContextCreate.
        // Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast
        // to create bitmap graphics contexts without alpha info.
        CGContextRef context = CGBitmapContextCreate(NULL,
                                                     width,
                                                     height,
                                                     bitsPerComponent,
                                                     bytesPerRow,
                                                     colorspaceRef,
                                                     kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);

        // Draw the image into the context and retrieve the new bitmap image without alpha
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
        CGImageRef imageRefWithoutAlpha = CGBitmapContextCreateImage(context);
        UIImage *imageWithoutAlpha = [UIImage imageWithCGImage:imageRefWithoutAlpha
                                                         scale:image.scale
                                                   orientation:image.imageOrientation];

        if (unsupportedColorSpace) {
            CGColorSpaceRelease(colorspaceRef);
        }

        CGContextRelease(context);
        CGImageRelease(imageRefWithoutAlpha);

        return imageWithoutAlpha;
    }
}

(该方法在SDWebImageDecoder.m中,版本为SDWebImage 3.7.0)。

我很困惑,因为这些temp objects将在方法返回后被释放,所以是否有必要使用autoreleasepool才能在之前释放它们? autoreleasepool也将占据记忆。

任何人都可以解释一下,谢谢!

答案

通过这个apple doc。有人提到

有三次你可能会使用自己的自动释放池块:

  • 如果您正在编写不基于UI框架的程序,例如命令行工具。
  • 如果编写一个创建许多临时对象的循环。您可以在循环内使用自动释放池块在下一次迭代之前处理这些对象。在循环中使用自动释放池块有助于减少应用程序的最大内存占用量。
  • 如果你产生一个辅助线程。一旦线程开始执行,您必须创建自己的自动释放池块;否则,您的应用程序将泄漏对象。 (有关详细信息,请参阅自动释放池块和线程。)

我不确定第一点,但SDWebImage肯定会使用autoreleasepool其他两点。

以上是关于为什么SDWebImage在decodeImageWithImage方法中使用@autoreleasepool块?的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发中SDWebImage加载图片不显示(图片地址在浏览器中能显示)

为啥所有异步图像加载(SDWebImage、AFNetworking)库都使用 UIImageView 而不是 UIImage?

ASIHttpRequest或者SDWebImage给UIImageView加载图片的逻辑是什么样子的

iOS——SDWebImage加载WebP图片

TableCell ImageView 使用 URL 设置图像:SDWebImage:仅调整第一行的大小

SDWebImage 下载后不显示(仅在重新打开 VController 后)