【问题标题】:Why did the SDWebImage use @autoreleasepool block in the decodedImageWithImage method?为什么 SDWebImage 在 decodedImageWithImage 方法中使用 @autoreleasepool 块?
【发布时间】:2018-08-20 05:00:38
【问题描述】:

如下面的代码 sn-p,它在这个方法中使用了@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 也会占用内存。

谁能解释一下,谢谢!

【问题讨论】:

    标签: ios memory-management sdwebimage autorelease


    【解决方案1】:

    通过这个apple doc。据说

    您可能会使用自己的自动释放池块的三种情况:

    • 如果您正在编写不基于 UI 框架的程序,例如命令行工具。

    • 如果您编写了一个创建许多临时对象的循环。 您可以在循环内使用自动释放池块在下一次迭代之前处理这些对象。在循环中使用自动释放池块有助于减少应用程序的最大内存占用。

    • 如果生成辅助线程。 您必须在线程开始执行后立即创建自己的自动释放池块;否则,您的应用程序将泄漏对象。 (有关详细信息,请参阅自动释放池块和线程。)

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

    【讨论】:

    • 提前致谢。我知道这些场合,看看方法及其被调用的方法,没有循环,并且该方法不仅用于子线程。所以我也觉得没必要,这些临时对象会在方法返回后释放
    • @george_luofz 在 func 中,SD 将图像解码为位图(或者您可以说在像素级别)。它存储该像素的所有可用数据。现在以图像分辨率为 1980x1980 的条件为条件。这里会消耗大量内存,可能会导致内存泄漏。
    • 也许我明白你在说什么。有可能发生。你是对的,而且坦克很多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 2012-01-14
    • 1970-01-01
    相关资源
    最近更新 更多