ios - 导致设备内存泄漏的位图

标签 ios objective-c memory-leaks bitmap core-graphics

我正在使用简单的位图技术将文本转换为图像,之后我将此图像划分为光栅,稍后我计算每个光栅矩形中黑色像素的百分比。在模拟器上一切正常,但在设备上崩溃。这里是一些相关代码

-(int)blackValue:(UIImage *)image rect:(CGRect)rect {
    int pixelInRect = (int)rect.size.width * rect.size.height;
    __block int blackCount = 0;
    ImageBitmap * imageBitmap = [[ImageBitmap alloc] initWithImage:image  bitmapInfo:(CGBitmapInfo)kCGImageAlphaNoneSkipLast];
    for (int x = 0; x <(int) rect.size.width; x++) {
        for (int y = 0; y < (int) rect.size.height; y++) {
            Byte * pixel = [imageBitmap pixelAtX:(int)rect.origin.x Y:(int)rect.origin.y];
            Byte red = pixel[0];
            if (red <  0.1)
            {
                blackCount++;
            }
        }
    }
    return blackCount/pixelInRect;
}

- (NSDictionary *)rasterizeBitmap:(UIImage *)image size:(CGFloat)size {
    CGFloat width =(int) (image.size.width/size);
    CGFloat height =(int) (image.size.height/size);
    NSMutableArray *fields = [NSMutableArray array];
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            CGRect rect = CGRectMake(x * size, y * size, size, size);
            CGPoint center = CGPointMake(x * size + size/2.0, image.size.height - (y * size + size/2.0));
            double black = [self blackValue:image rect:rect];
            Field * field = [[Field alloc] init];
            field.center = center;
            field.black = black;
            [fields addObject:field];
        }
    }
    return @{@"width":@(width) , @"fields":fields};
}

当我尝试在配置文件中运行它时,我得到了以下结果

enter image description here

有人可以建议我如何解决内存问题吗?

最佳答案

问题是您在 ImageBitmap 中手动分配内存对象,但您永远不会释放它。

两个可疑点是位图上下文 (context) 和位图数据 (contextData)。这两个都不是由 ARC 管理的,因此您需要在完成后自行释放它们。

在 ARC 中,您可以简单地在 ImageBitmap 类中实现 dealloc 方法,并将清理代码放在那里。

例如:

-(void) dealloc {
    CGContextRelease(context); // releases the bitmap context, if it was created (CGContextRelease checks for NULL)
    free(contextData); // releases the bitmap data (it was explicitly created, so no need to check)
}

同样值得注意的是,您应该使 init 不可用,并标记您指定的初始化程序。

这是因为您不能在未通过自定义创建实例的情况下使用imageFromContextpixelAtX:Y: 实例方法initWithSize:bitmapInfo: 初始化程序,因为它创建位图上下文并为位图数据分配内存。

因此,如果您通过调用 init 来创建您的实例,并调用您的实例方法之一,您很可能会崩溃。

要解决此问题,您可以在 ImageBitmap.h 文件中将 init 方法标记为不可用,同时标记您的 initWithSize:bitmapInfo: 方法作为指定的初始化器。

-(instancetype) init NS_UNAVAILABLE;

-(id)initWithSize:(CGSize)size bitmapInfo:(CGBitmapInfo)bmInfo NS_DESIGNATED_INITIALIZER;

所有 NS_UNAVAILABLE 所做的就是阻止您通过调用 init 来创建您的实例,迫使您使用您的自定义初始化器。

如果您尝试执行 [[ImageBitmap alloc] init],编译器将显示以下错误:

enter image description here

所有 NS_DESIGNATED_INITIALIZER 所做的就是确保 ImageBitmap 中的任何额外初始化器必须通过您的初始化器创建新实例,如果它们不这样做,则会向您显示以下警告:

enter image description here

See here for more info on NS_DESIGNATED_INITIALIZER.

现在,实际上这些实际上只是形式,因为您是唯一要使用它的人,并且您知道您必须使用自定义初始化程序。但是,如果您想与其他人共享您的代码,最好办理好这些手续。

关于ios - 导致设备内存泄漏的位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35797930/

相关文章:

objective-c - 用于 iOS ARC 问题的 BWDB SQLite 包装器

objective-c - iPhone SDK如何从照片库中获取完整的图像?

objective-c - 如何将多个 ViewController 添加到我的 UIPageViewController?

delphi - 使用控制台应用程序报告关闭时的内存泄漏

qt - OpenGL 纹理映射内存泄漏

ios - 滚动 UIScrollView 自动滚动 - 就像提词器(Swift)

ios - 如何处理“设置”应用中位置权限的更改

Java - x32 和 x64 之间的奇数内存消耗

ios - 如何阻止我的 tableView 单元格重复使用其中的按钮?

ios - iPhone 7 Plus AVPlayer 周围有边框(白色颜色不匹配)